Skip to content

Instantly share code, notes, and snippets.

@keeferrourke
Created June 5, 2019 16:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keeferrourke/7c36fb0b507823ffec80b18836eee5fa to your computer and use it in GitHub Desktop.
Save keeferrourke/7c36fb0b507823ffec80b18836eee5fa to your computer and use it in GitHub Desktop.
Make some sense of JVM access modifiers
import org.objectweb.asm.Opcodes
data class AccessModifier(val code: Int, val name: String)
enum class ClassPart {
CLASS,
METHOD,
FIELD,
MODULE,
MODULE_REQUIRES
}
/**
* Unmasks an integer and pairs it with a string of human readable JVM access modifiers.
*/
fun Int.toAccessModifier(part: ClassPart = ClassPart.CLASS): AccessModifier {
val modifier = buildString {
var remaining = this@toAccessModifier
var bit: Int
while (remaining != 0) {
bit = Integer.lowestOneBit(remaining)
when (bit) {
Opcodes.ACC_PUBLIC -> append("public")
Opcodes.ACC_PRIVATE -> append("private")
Opcodes.ACC_PROTECTED -> append("protected")
Opcodes.ACC_STATIC -> append("static")
Opcodes.ACC_FINAL -> append("final")
0x0020 -> {
// ACC_SUPER, ACC_SYNCHRONIZED, ACC_OPEN, and ACC_TRANSITIVE all share this value.
when (part) {
ClassPart.CLASS -> append("super")
ClassPart.METHOD -> append("synchronized")
ClassPart.MODULE_REQUIRES -> append("transitive")
ClassPart.MODULE -> append("open")
else -> throw IllegalStateException("Encountered unexpected opcode: 0x0020")
}
}
0x0040 -> {
// ACC_VOLATILE, ACC_BRIDGE, ACC_STATIC_PHASE all share this value.
when (part) {
ClassPart.METHOD -> append("bridge")
ClassPart.FIELD -> append("volatile")
ClassPart.MODULE_REQUIRES -> append("(requires static)")
else -> throw IllegalStateException("Encountered unexpected opcode: 0x0040")
}
}
0x0080 -> {
// ACC_VARARGS, ACC_TRANSIENT share this value.
when (part) {
ClassPart.METHOD -> append("varargs")
ClassPart.FIELD -> append("transient")
else -> throw IllegalStateException("Encountered unexpected opcode: 0x0080")
}
}
Opcodes.ACC_NATIVE -> append("native")
Opcodes.ACC_INTERFACE -> append("interface")
Opcodes.ACC_ABSTRACT -> append("abstract")
Opcodes.ACC_STRICT -> append("strictfp")
Opcodes.ACC_SYNTHETIC -> append("synthetic")
Opcodes.ACC_ANNOTATION -> append("annotation")
Opcodes.ACC_ENUM -> append("enum")
0x8000 -> {
// ACC_MANADATED and ACC_MODULE share this value.
when (part) {
ClassPart.MODULE -> append("mandated")
ClassPart.CLASS -> append("module")
else -> throw IllegalStateException("Encountered unexpected opcode: 0x8000")
}
}
Opcodes.ACC_DEPRECATED -> append("DEPRECATED")
}
remaining -= bit
append(" ")
}
trim()
if (isEmpty()) {
append("package-private")
}
}
return AccessModifier(this, modifier.trim())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment