上下文: 一个新类说Bar,在运行时被注入JVM。这个类属于com.foo这个包。 对此类的引用将注入到属于同一包的另一个类中。 每次加载新类时可能都有不同的名称 - 因此不能将其指定为任何配置文件的一部分 - 例如不能在build.xml中指定作为jar文件的一部分包含。
问题: 在类加载时,jvm抛出一个错误 - java结果1.尽管我无法确定地确定根本原因,但看起来类加载器找不到新注入的类。 服务器以详细模式运行,该模式显示JVM加载的类列表,并且可以看到这个新注入的类已加载。
问题: 新注入的类是否已经在类路径中?如果不是如何设置它?
[编辑] - 在问题中添加一些代码。
代码段 - 1:下面的代码段是从PreMain方法调用的 - Premain方法将由JVM代理调用,并在运行时注入检测引用。 Premain方法从一个方法中注入一个新类--Bar - 和一个对这个新类的引用 - returnsABool() - 在一个现有的类中 - ExistingClass。
public static void premain(String agentArgs, Instrumentation inst) {
// 1. Create and load the new class - Bar
String className = "Bar";
byte [] b = getBytesForNewClass();
//override classDefine (as it is protected) and define the class.
Class clazz = null;
try {
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class cls = Class.forName("java.lang.ClassLoader");
java.lang.reflect.Method method =
cls.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class, int.class, int.class });
// protected method invocation
method.setAccessible(true);
try {
Object[] args = new Object[] { className, b, new Integer(0), new Integer(b.length)};
clazz = (Class) method.invoke(loader, args);
} finally {
method.setAccessible(false);
}
} catch (Exception e) {
System.err.println(
"AllocationInstrumenter was unable to create new class" + e.getMessage());
e.printStackTrace();
}
// 2. Inject some lines of code into the returnsABool method in ExistingClass class that references Bar
inst.addTransformer(new CustomInstrumenter(), true);
// end of premain method
}
代码sement 2:方法returnsABool()需要用注释进行字节注入 线条如下所示。字节注入的代码也是从PreMain方法调用的。
public class ExistingClass{
public static boolean returnsABool() {
// Code within comments is byte-injected, again as part of the pre-main method
/*
String str = Bar.get();
if (str != "someValue") {
return true;
}
*/
return false;
}
}
ExistingClass的字节码注入 - 使用asm库
完成{
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/Bar", "get", "()Ljava/lang/String;");
mv.visitLdcInsn("some constant here");
Label l1 = new Label();
mv.visitJumpInsn(Opcodes.IF_ACMPNE, l1);
mv.visitInsn(Opcodes.ICONST_0); Label l2 = new Label();
mv.visitJumpInsn(Opcodes.GOTO, l2);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(Opcodes.ICONST_1);
mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
mv.visitInsn(Opcodes.IRETURN);
mv.visitMaxs(2, 0);
mv.visitEnd();
}
答案 0 :(得分:1)
我怀疑你的字节码生成有问题,以下ASM代码适用于我:
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/Bar", "get", "()Ljava/lang/String;");
Label l1 = new Label();
mv.visitLdcInsn("some constant here");
mv.visitJumpInsn(Opcodes.IF_ACMPEQ, l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(Opcodes.ICONST_1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 1, new Object[] {Opcodes.INTEGER});
mv.visitInsn(Opcodes.IRETURN);
mv.visitLabel(l1);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitFrame(Opcodes.F_SAME, 0, null, 1, new Object[] {Opcodes.INTEGER});
mv.visitInsn(Opcodes.IRETURN);
mv.visitMaxs(2, 1);
mv.visitEnd();
另请注意:
str.equals(str2)