【问题标题】:Java agent instrumentation error: Could not initialize class java.lang.invoke.CallSiteJava 代理检测错误:无法初始化类 java.lang.invoke.CallSite
【发布时间】:2017-03-28 04:31:03
【问题描述】:

我正在尝试打印出 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());
  } 
}

清单.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 错误。

【问题讨论】:

标签: java instrumentation javaagents


【解决方案1】:

在下面找到解决方法。只是我在代理类的 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());
    }
}

【讨论】:

  • 在检测通过 spark-submit 加载的 spark-jobs 时,我也遇到了同样的情况。这种解决方法有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-28
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多