Setting a class for a newly introduced class

Context: A new class, say Bar, is injected into the JVM at runtime. This class belongs to the say com.foo package. A reference to this class is entered in another class that belongs to the same package. A new class may have a different name each time it is loaded - therefore, it cannot be specified as part of any configuration file - for example, it cannot be specified in the build.xml file, which will be included as part of the jar file.

Question: At the moment the jvm class is loaded, it generates an error - java Result 1. Although I can’t definitively determine the root cause, it seems that the newly introduced class was not found by the class loader. The server was started in verbose mode, which shows a list of classes loaded by the JVM, and this newly introduced class will be loaded.

Question: Is a newly introduced class already in classpath? If you do not install it?

[Change] - adding some code to the question.

Code Segment - 1: This code segment below is called from the PreMain method. The Premain method will be called by the JVM agent and will enter a reference to the hardware at runtime. The Premain method introduces 1 new class - Bar - and 1 reference to this new class from the method - returnsABool () - to the existing class - 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 code: the returnsABool () method should be entered in the line comment bytes shown below. The code for entering the byte is also called from the PreMain method.

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;
    }
}

Insert byte code for ExistingClass - performed using asm library

{  
    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();   
}
+5
source share
1 answer

, - , 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)
  • , , ( , )
+1

All Articles