Contexto: Una nueva clase, por ejemplo, Bar, se inyecta en la JVM en tiempo de ejecución. Esta clase pertenece a un paquete decir com.foo. Una referencia a esta clase se inyecta en otra clase que pertenece al mismo paquete. La nueva clase puede tener un nombre diferente cada vez que se carga, por lo que no se puede especificar como parte de ningún archivo de configuración, p. no se puede especificar en build.xml para incluirlo como parte de un archivo jar.configuración del classpath para una clase recientemente inyectada
Issue: En el tiempo de carga de clase, jvm arroja un error - java Resultado 1. Aunque no puedo determinar de manera concluyente la causa raíz, parece que la clase recién inyectada no está siendo encontrada por el cargador de clases. El servidor se ejecutó en modo detallado que muestra la lista de clases cargadas por la JVM y esta clase recién inyectada se ve cargada.
Pregunta: ¿La clase recién inyectada ya está en el classpath? Si no, ¿cómo configurarlo?
[Editar] - agregando un código a la pregunta.
Segmento de código - 1: este segmento de código siguiente se llama desde el método PreMain - El agente de JVM llamará al método Premain e inyectará la referencia de instrumentación en tiempo de ejecución. El método Premain inyecta 1 nueva clase - Barra - y 1 referencia a esta nueva clase desde un método - devuelve ABool() - en una clase existente - 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
}
Código Sement 2: El returnsABool método() necesita ser byte-inyectados con el líneas de comentarios que se muestran abajo. El código para insertar byte esto también se llama desde el método 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;
}
}
Byte inyección de código para ExistingClass - hace usando la biblioteca 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();
}
¿Cómo, específicamente, se está "inyectando" la clase? ¿Se crea y carga dinámicamente por el cargador de clases? –
Algún código de Java sería útil, de lo contrario es muy difícil ayudarte. Además, tal vez esta pregunta sea útil: http://stackoverflow.com/q/4210346/74694 –
Muestre un ejemplo mínimo que demuestre el problema que tiene. –