I have dynamically-generated model classes that I use in drools. It seems that these dynamically generated classes expose a different structure with regard to reflection than if they would have been defined by normal java code. I would like to understand why byte-buddy generates different byte-code and if I can control this behaviour, or if this is expected bytecode and drools "should" (if they decide so) support it.
These model classes have two base classes:
public abstract class Vehicle<TEngine extends Engine> { public abstract TEngine getEngine();
...
public abstract class Engine { then I have an `engine` class:
engineClass = new ByteBuddy() .subclass(Engine.class).name("drools.issues.model.vehicles.GasolineEngine") //...
and a vehicle class like this:
TypeDescription.Generic generic = TypeDescription.Generic.Builder.parameterizedType(Vehicle.class, engineClass).build(); vehicleClass = (Class<? extends Vehicle>) new ByteBuddy().subclass(generic) //.
If I do a subclass with normal Java code instead, drools works well:
public class DieselCar extends Vehicle<DieselEngine> {
but with my bytebuddy-generated class vehicleClass, I get:
java.lang.ClassCastException: class sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to class java.lang.Class (sun.reflect.generics.reflectiveObjects.TypeVariableImpl and java.lang.Class are in module java.base of loader 'bootstrap').
reflection of java class exposes an instance of Class always, so drools does a blind cast of Type to Class. However, bytebuddy-generated class exposes TypeVariableImpl instead.
If I .subclass directly to Vehicle.class instead of the generic TypeDescriptor, drools does not complain (but the type information is not there, of course).
Any hint? is this way of subclassing for generics expected in byte-buddy? why is this different from java-compiler-generated class? are both "legal" java code?