raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.28k stars 807 forks source link

Use bytebuddy in a Javac Compiler plugin #1482

Closed Auties00 closed 1 month ago

Auties00 commented 1 year ago

Hello, I'm trying to make ByteBuddy work within a Javac Compiler plugin(com.sun.source.util.Plugin). In short, I've managed to locate and read the compiled .class files, but I can't find a way to load them without a ClassLoader. Is it possible to load the raw bytecode directly? If it isn't, I could load the compiled .class into a custom URLClassLoader alongside the classpath, but then I might have an issue if, for example, class A and B depend on each other. Is there a way to prevent ByteBuddy from loading types within the ByteCode that are not loaded in the ClassLoader at that time? (I need to define new methods, that's why I'm not using ByteBuddy#decorate) Thanks in advance!

raphw commented 1 year ago

There's ByteArrayClassLoader. Wouldn't that work for you?

Auties00 commented 1 year ago

There's ByteArrayClassLoader. Wouldn't that work for you?

I saw that class, but as far as I can tell, it needs an instance of TypeDescription which can only be obtained from a Class<?>. Maybe I'm missing something though. Also, if I load it this way, is there a way for me to ignore types that might not be known at that moment? Or maybe that happens directly when loading bytecode from a byte array instead of a Class<?> ?

raphw commented 1 year ago

There's a constructor that takes strings instead of type descriptions.

Auties00 commented 1 year ago

There's a constructor that takes strings instead of type descriptions.

Do you mind sending a javadoc reference? I can't seem to find it

raphw commented 1 year ago

https://javadoc.io/doc/net.bytebuddy/byte-buddy/1.10.2/net/bytebuddy/dynamic/loading/ByteArrayClassLoader.html#ByteArrayClassLoader-java.lang.ClassLoader-boolean-java.util.Map-

Auties00 commented 1 year ago

https://javadoc.io/doc/net.bytebuddy/byte-buddy/1.10.2/net/bytebuddy/dynamic/loading/ByteArrayClassLoader.html#ByteArrayClassLoader-java.lang.ClassLoader-boolean-java.util.Map-

Thanks, but this still involves loading a Class<?>. This means that all types referenced by that Class need to be known by the class loader. Take this example:

class First {
  static {
     Second.someMethod();
  }

  static void someMethod() {
     // Do something
  }
}
class Second {
  static {
     First.someMethod();
  }

  static void someMethod() {
     // Do something
  }
}

Either First or Second is going to be compiled first, so if I try to do my instrumentation without the other class a NoClassDefError will be thrown. Is there any way to simply ignore unknown types?

1057105012 commented 1 year ago

If there is a large number of NoClassDefError visually, it will cause a double free error of 1.8. I hope this can also be paid attention to. Thank you to the author JDK-8178870, you can veto some destruction schemes given in the code

raphw commented 1 year ago

It seems to be backported to 8.