如何阻止Byte Buddy实现参数化类型时具体化类型参数?
解决Byte Buddy解析泛型接口时提前加载未生成类型的问题
针对你遇到的TypeNotPresentException,核心问题是Byte Buddy在解析Reals接口的泛型父类Provider<Real>时,会触发Real类型的加载,而此时该类型尚未生成。以下是几种可行的解决策略:
1. 自定义TypeDescription屏蔽泛型参数解析
通过创建自定义的TypeDescription实现,手动将泛型参数替换为Object,避免Byte Buddy解析未生成的Real类型。
实现步骤:
- 继承
TypeDescription.ForLoadedType,重写getGenericInterfaces方法擦除泛型参数:
import net.bytebuddy.description.type.TypeDescription; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; class RawTypeDescription extends TypeDescription.ForLoadedType { public RawTypeDescription(Class<?> type) { super(type); } @Override public List<TypeDescription.Generic> getGenericInterfaces() { return super.getGenericInterfaces().stream() .map(this::eraseGenerics) .collect(Collectors.toList()); } private TypeDescription.Generic eraseGenerics(TypeDescription.Generic generic) { if (generic instanceof TypeDescription.Generic.ParameterizedType) { TypeDescription.Generic.ParameterizedType paramType = (TypeDescription.Generic.ParameterizedType) generic; // 将所有泛型参数替换为Object,避免解析Real return TypeDescription.Generic.ParameterizedType.of( paramType.getRawType(), Collections.nCopies(paramType.getTypeArguments().size(), TypeDescription.Generic.OBJECT) ); } return generic; } }
- 在Byte Buddy配置中使用自定义
TypeLocator,为lang.Reals接口返回上述自定义类型描述:
ByteBuddy byteBuddy = new ByteBuddy(JAVA_V9) .with(TypeValidation.DISABLED) .with(new TypeLocator() { @Override public TypeDescription locate(String name) throws IllegalArgumentException { if ("lang.Reals".equals(name)) { // 使用false参数加载类,避免初始化及关联类型加载 Class<?> realsClass = Class.forName(name, false, Thread.currentThread().getContextClassLoader()); return new RawTypeDescription(realsClass); } return super.locate(name); } }) .with(MethodGraph.Compiler.Default.forJVMHierarchy);
2. 手动构建原始类型的TypeDescription
绕过Byte Buddy的自动泛型解析,直接手动构建lang.Reals的原始类型描述,不包含泛型参数信息:
ClassLoader loader = Thread.currentThread().getContextClassLoader(); // 加载lang.Reals但不初始化 Class<?> realsClass = Class.forName("lang.Reals", false, loader); // 构建原始类型的TypeDescription TypeDescription.Generic realsRawType = TypeDescription.Generic.Builder.rawType(realsClass).build(); // 在生成类时使用该原始类型 byteBuddy.subclass(Object.class) .implement(realsRawType) // 绑定本地Reals接口的默认方法 .method(ElementMatchers.any()) .intercept(MethodCall.invokeDefaultMethod(yourLocalRealsInterface)) .make();
3. 手动生成桥接方法,禁用自动泛型桥接
如果需要保留桥接方法,可以手动定义桥接逻辑,避免Byte Buddy通过泛型解析自动生成:
byteBuddy.subclass(Object.class) .implement(yourLocalRealsInterface) // 实现本地Reals接口的方法 .method(ElementMatchers.named("get")) .intercept(MethodCall.invokeDefaultMethod(yourLocalRealsInterface)) // 手动添加针对Provider<Object>的桥接方法 .defineMethod("get", Object.class, Modifier.PUBLIC) .intercept(MethodCall.invokeVirtual(ElementMatchers.isDeclaredBy(yourLocalRealsInterface), "get")) .make();
这些策略的核心都是阻止Byte Buddy解析Provider<Real>中的Real类型,将泛型接口视为原始类型处理,从而避免提前加载未生成的类型。
内容的提问来源于stack exchange,提问作者raner
相关产品推荐
相关产品推荐

