1

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.

5
  • If you have the bytecode as a byte[] then you could construct a ByteArrayInputStream. Commented Oct 16, 2016 at 19:02
  • I do have it, but it's generated on different place of the app and in different time. If I start to collect all the byte[] for each proxy class it is generated, it's going to be too much. Anyway, I am exploring this option. Commented Oct 16, 2016 at 19:04
  • Since you don't explicitly state what you need to do with the InputStream, I can only guess, but ObjectInputStream may be helpful? ref: javadoc for ObjectInputStream Commented Oct 16, 2016 at 19:12
  • @mangotang thanx - but no, I need it for further bytecode change (question updated) Commented Oct 16, 2016 at 19:14
  • First of all, you should get rid of the intermediate URL step, as that requires defining a custom protocol and implementing a protocol handler for in-memory representations. Just use, e.g. Foo.class.getResourceAsStream("Foo.class"). That way, the ClassLoader can return a ByteArrayInputStream without the need to support URLs. If you change it to use temporary files to save memory in-between, the application logic doesn’t change. Commented Oct 17, 2016 at 15:26

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Heya Rafael! Thanx for the answer; just agent is not always available as an option. I solved my problem in other way, but still, i might collect generated bytecode in some temp files (unless they are created every time on usage)
does anybody created agent for this?
seems like this github.com/rmannibucau/dumping-javaagent if it works
confirm. It works on Java16!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.