Search code examples
javaclassloaderbytecodebytecode-manipulation

Get InputStream of a class that is dynamically created (using bytecode)?


I create a class dynamically - by constructing the bytecode and loading it with class loader. Later, I need to get InputStream of this class. With common class, I get this by getting resource URL for this class and then opening the stream (url.openStream()). Obviously, here I can't do that, as dynamically loaded class does not have the URL.

How can I get InputStream of dynamically created class?

The only solution I can think of atm is to save the bytecodes to some temp file/memory and then to provide InputStream from it.

EDIT

I need InputStream to make another bytecode change on top of existing.


Solution

  • If the class loader does not provide a class's byte code via either getResource or getResourceAsStream (this is legal, the class loader contract does not specify such a thing), you can still use a Java agent for asking the VM to create the byte code for you.

    For example, you can register the following transformer:

    instrumentation.addTransformer(new ClassFileTransformer() {
      @Override
      public byte[] transform(ClassLoader loader,
                              String name,
                              Class<?> classBeingRedefined,
                              ProtectionDomain pd,
                              byte[] classFileBuffer) {
        doSomethingWith(classFileBuffer);
        return null;
      }
    }, true);
    

    After attaching a Java agent, you can call: instrumentation.retransform(someGeneratedClass) to trigger the above class file transformer which will contain the generated type's class file even if it is not available from its class loader.