Java代理程序检测错误:无法初始化类java.lang.invoke.CallSite

时间:2017-03-28 04:31:04

标签: java instrumentation javaagents

我试图打印出java程序中使用的所有方法。为此,我创建了一个java代理,它使用检测来打印出每个被调用的方法。该代理适用于简单的HelloWorld类型程序,但在尝试在更复杂的程序上使用时失败。我不知道是什么导致它失败。

代码

(取自appcrawler并稍作修改):

agent.jar源代码:

SimpleTransformer.java:

package test;

import java.security.*;
import java.lang.instrument.*;
import java.util.*;
import javassist.*;

public class SimpleTransformer implements ClassFileTransformer {

  public SimpleTransformer() {
    super();
  }

  public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException {
    return transformClass(redefiningClass,bytes);
  }

  private byte[] transformClass(Class classToTransform, byte[] b) {
    ClassPool pool = ClassPool.getDefault();
    CtClass cl = null;
    try {
      cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
      CtBehavior[] methods = cl.getDeclaredBehaviors();
      for (int i = 0; i < methods.length; i++) {
        if (methods[i].isEmpty() == false) {
          changeMethod(methods[i]);
        }
      }
      b = cl.toBytecode();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    finally {
      if (cl != null) {
        cl.detach();
      }
    }
    return b;
  }

  private void changeMethod(CtBehavior method) throws NotFoundException, CannotCompileException {
    /*if (method.getName().equals("doIt")) {
      method.insertBefore("System.out.println(\"started method at \" + new java.util.Date());");
      method.insertAfter("System.out.println(\"ended method at \" + new java.util.Date());");
    }*/



          //MY CODE
      //!Modifier.isAbstract(method.getModifiers()) -- abstract methods can't be modified. If you get exceptions, then add this to the if statement.
      //native methods can't be modified.
      if (!Modifier.isNative(method.getModifiers()) && !Modifier.isAbstract(method.getModifiers())) {
          String insertString = "System.out.println(\"started method " + method.getName() + "\");";
          method.insertBefore(insertString);
      }
  }

SimpleMain.java:

package test;

import java.lang.instrument.Instrumentation;

public class SimpleMain {
  public static void premain(String agentArguments, Instrumentation instrumentation) {  
    instrumentation.addTransformer(new SimpleTransformer());
  } 
}

MANIFEST.MF:

Manifest-Version: 1.0
Boot-Class-Path: javassist.jar
Premain-Class: test.SimpleMain

错误

Exception in thread "main"
java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: Could not initialize class java.lang.invoke.CallSite
        at sun.net.www.protocol.http.HttpURLConnection.getNetProperty(Unknown So
urce)
        at sun.net.www.protocol.http.HttpURLConnection.<clinit>(Unknown Source)
        at sun.net.www.protocol.http.Handler.openConnection(Unknown Source)
        at sun.net.www.protocol.http.Handler.openConnection(Unknown Source)
        at java.net.URL.openConnection(Unknown Source)
        at java.net.URL.openStream(Unknown Source)
        at io.ludi.myProgram.ConfigReader.readConfig(ConfigReader.java:41)
        at io.ludi.myProgram.ConfigReader.read(ConfigReader.java:68)
        at io.ludi.myProgram.App.main(App.java:23)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class java.lang.
invoke.CallSite
        at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(Unknown Source)

        at java.lang.invoke.MethodHandleNatives.linkCallSite(Unknown Source)

代码工作正常,没有附加java代理。我不明白为什么它会抛出ClassDefNotFound错误。

1 个答案:

答案 0 :(得分:0)

找到以下解决方法。只是我在Agent Class中的premain()方法的开头用Class.forName(“ java.lang.invoke.CallSite”)加载了CallSite。在添加Transformer类之前已加载。

public class SimpleMain {

    public static void premain(String agentArgs, Instrumentation inst) {

            Class t = null;
            try {
                **t = Class.forName("java.lang.invoke.CallSite");**
            } catch (Throwable e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } 

            .
            .
            .
            instrumentation.addTransformer(new MyTransformer());
    }
}