Given an arbitrary Class
instance, including one that's runtime generated (no .class
file on disk), is there any way to get the class bytes?
-
Have you looked at [Apache Bytecode Engineering Library](https://commons.apache.org/proper/commons-bcel/index.html)? – Mick Mnemonic Jan 28 '16 at 20:28
2 Answers
In general, this is not possible. While loading a class, JVM parses its bytecode and converts it to the internal representation. After that JVM is free to forget the original bytecode, and that's what really happens with HotSpot JVM.
However, with the certain hacks it is possible to inspect the internal class representation and convert it back to a valid class file (though it will differ from the original bytecode). Such process is used in HotSpot JVM to reconstitute a class file for Instrumentation purposes.
As a proof of concept, I've written a program that extracts processed bytecode of a loaded class from JVM memory using Unsafe
. This is only for a demo; don't ever try this in production.
EDIT
You can also get class file data (possibly modified by JVM) using Instrumentation API. This requires a Java agent loaded either at VM bootstrap (using -javaagent
VM option) or at runtime via Dynamic Attach mechanism.
Here is an example of such agent: GetBytecode.java.
Finally, if you don't mind using native code, there are JVMTI functions GetConstantPool and GetBytecodes to obtain the bytecodes of the particular Java method.
Here is a JVMTI example.
-
Note: Instrumentation will even allow you to see the byte code of dynamically created classes such as Lambdas. +1 – Peter Lawrey Feb 01 '16 at 13:36
-
@apangin is there a way to generate the method definition using its byte codes and its constant pool, using jvmti? – kumarD Mar 02 '17 at 06:40
-
@kumarD Not sure what you mean. Constant Pool is a property of a class, while bytecode is an attribute of a method. In what form would you like to get a method definition? – apangin Mar 05 '17 at 23:08
String classFile = "/" + Object.class.getName().replace('.', '/') + ".class";
System.out.println(classFile);
URL url = Test.class.getResource(classFile);
System.out.println(url);
produces this output.
/java/lang/Object.class
jar:file:/usr/java/jdk1.8.0_60/jre/lib/rt.jar!/java/lang/Object.class
so you may use url
to read in bytes. (not applicable for runtime generated classes)

- 2,714
- 1
- 15
- 19
-
BTW, this will be invalid starting from JDK 9, because there won't be *rt.jar* with the original bytecode any more. – apangin Jan 28 '16 at 21:13
-
4or simple: `Object.class.getResource("Object.class")`, or for an arbitrary `Class` object: `classObj.getResource(classObj.getSimpleName()+".class")`. @apangin: this will continue to work with Java 9 as that’s the point of abstraction. It’s just that the URL will no longer have a `jar:` but a `jrt:` scheme. – Holger Jan 29 '16 at 16:34