我有一个场景,我需要从未知来源加载类并实例化它们以进行模拟——我不需要运行代码,但方法和属性必须在结果实例中。我还需要类的名称保持不变,以便将其实例分配给其他已加载类的该类型的字段。有时类实例化由于ExceptionInLaunalizerError
而失败,使类处于无效状态,无法恢复。我不知道哪个类会事先失败。
考虑一下这一点:
class A {
static {
// Throws exception, resulting in 'A' changing to an error state
}
}
class B {
// In case 'A' could not be instantiated properly, I wish to mock
// it so it can be assigned to this field
private A someField;
}
以下是我想到的:
我错过什么了吗?有没有更简单的方法来实现我的目标?
我最终找到了某种可行的解决方案,但我无法让Byte Buddy在没有静态初始值设定项的情况下过滤出类(它将计算每个类的帧)
agentBuilder = agentBuilder.type(ElementMatchers.any())
.transform((builder, type, classLoader, module) -> builder
.visit(new AsmVisitorWrapper.AbstractBase() {
@Override
public int mergeWriter(int flags) {
return flags | ClassWriter.COMPUTE_FRAMES;
}
@Override
public ClassVisitor wrap(TypeDescription instrumentedType, ClassVisitor classVisitor,
Implementation.Context implementationContext, TypePool typePool,
FieldList<FieldDescription.InDefinedShape> fields,
MethodList<?> methods, int writerFlags, int readerFlags) {
if (methods.stream().noneMatch(MethodDescription::isTypeInitializer)) {
return classVisitor;
}
return new ClassVisitor(Opcodes.ASM9, classVisitor) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature, String[] exceptions) {
MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor,
signature, exceptions);
methodVisitor = new JSRInlinerAdapter(methodVisitor, access,
name, descriptor,
signature, exceptions);
if (name.equals("<clinit>")) {
methodVisitor = new TryCatchBlockSorter(methodVisitor, access, name,
descriptor, signature, exceptions);
methodVisitor = new MethodVisitor(Opcodes.ASM7, methodVisitor) {
private final Label start = new Label();
private final Label end = new Label();
private final Label handler = new Label();
@Override
public void visitCode() {
super.visitCode();
visitTryCatchBlock(start,
end,
handler,
"java/lang/RuntimeException");
visitLabel(start);
}
@Override
public void visitMaxs(int maxStack, int maxLocals) {
visitJumpInsn(Opcodes.GOTO, end);
visitLabel(handler);
visitInsn(Opcodes.RETURN);
visitLabel(end);
super.visitMaxs(maxStack, maxLocals);
}
};
}
return methodVisitor;
}
};
}
}));
此外,我在某些类上遇到以下异常,可能是Byte Buddy错误?
[Byte Buddy] ERROR ch.qos.logback.core.util.COWArrayList [ClassLoader@3b00856b, unnamed module @4189d70b, loaded=false]
java.lang.NullPointerException
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reducing.onGenericArray(TypeDescription.java:2326)
at net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reducing.onGenericArray(TypeDescription.java:2281)
at net.bytebuddy.description.type.TypeDescription$Generic$OfGenericArray.accept(TypeDescription.java:4415)
at net.bytebuddy.description.method.MethodDescription$Token.asSignatureToken(MethodDescription.java:1915)
at net.bytebuddy.description.method.MethodList$AbstractBase.asSignatureTokenList(MethodList.java:109)
at net.bytebuddy.dynamic.scaffold.inline.RebaseDynamicTypeBuilder.make(RebaseDynamicTypeBuilder.java:227)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:10438)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10374)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1600(AgentBuilder.java:10140)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10833)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10771)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10330)
at net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$ByteBuddy$ModuleSupport.transform(Unknown Source)
at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
如果一个类未能加载,它将永远被破坏。您所能做的是,在加载类之前,通过操纵它们的字节码来插入这些类。例如,可以使用Byte-Buddy重新定义类,以完全删除静态初始值设定项。如果使用Mockito另外模拟这些类,那么如果选择模拟它们,它们将无法执行任何代码。
您可以通过添加Java代理或实现自定义的类加载器(在定义之前显式转换任何类)来插入类。
我通过解决一些黑客等级问题来学习java。下面的代码是关于学习静态初始值设定项块的。例外情况是thown和Capture,但程序仍在运行,我不确定原因。 输入:-1,2 预期输出:java.lang.例外:宽度和高度必须为正 实际输出:宽度和高度必须为正-2
我对Swift类有一个问题。我有UITableViewController类和UITableViewCell类的swift文件。我的问题是UITableViewCell类和网点。这个类有一个错误Class“HomeCell”没有初始化程序,我不明白这个问题。 感谢您的回复。
问题内容: 我对某些文件有引用(在的选项卡中进行配置)。我可以访问和实例化那些文件中包含的类,因此它们包含在类路径中。 我希望这些类将自己注册到全局静态注册表中,因此我向所有这些类添加了一个静态初始化程序块: 我有几个此类都应该注册到的类(这只是一个带有a的类)。但是,每当我访问时,它都不包含任何值。 我读到静态初始值设定项是在首次加载该类时执行的,并且由于我没有在代码中的任何地方直接引用这些类,
我想将一些对象实例绑定到使用Javassist创建的类。该对象是从某个源读取的,数据是预先未知的。 但当我检查API时,Javassist似乎创建了一个真正的字节码,它以“调用这个”或“实例化那个”或“使用这个常量”的形式存储初始化。 有没有办法让Javassist向运行时给定的现有实例添加一个初始化的静态字段?
问题内容: 我似乎无法在有角度的引导程序标签集中设置初始标签。它始终将最左侧的选项卡设置为活动状态。 给定html: 和js: 见柱塞 2013年8月6日更新:现在已在上游修复,请参见github问题。 问题答案: 似乎(静态)选项卡会覆盖运行指令时传递给活动对象的所有内容。我认为这是一个错误。快速又肮脏,您可以使用具有0秒延迟的超时来设置活动状态。至少在插塞中,这不会引起任何闪烁。在您的控制器中
我有2个班: A类: B类: 我创建了一个主类,它只创建了一个新的: 我得到的输出是: 如您所见,在静态初始值设定项之前调用了的构造函数。 我知道这与我创建的循环依赖有关,但我的印象是静态初始化器应该总是在构造函数之前运行。 发生这种情况的原因是什么(技术上在java实现中)? 是否建议一起避免静态初始化器?