当前位置: 首页 > 知识库问答 >
问题:

使用JavaAgent向类路径添加类

牛嘉谊
2023-03-14

我正在使用Java代理和Javassist向一些JDK类添加一些日志记录。实际上,当系统加载一些TLS类时,Javassist会向它们添加一些额外的字节码,以帮助我调试一些连接问题。

问题是,考虑到这个类包含在代理jar中:

package com.something.myagent;
public class MyAgentPrinter {
    public static final void sayHello() {
        System.out.println("Hello!");
    }
}

在我的代理的转换方法中,假设我试图使用javassist调用该类:

// this is only called for sun.security.ssl.Handshaker
ClassPool cp = getClassPool(classfileBuffer, className);
CtClass cc = cp.get(className);
CtMethod declaredMethod = cc.getDeclaredMethod("calculateKeys");
declaredMethod.insertAfter("com.something.myagent.MyAgentPrinter.sayHello();");
cc.freeze();
return cc.toBytecode();

你认为这行得通,但我得到了这个:

java.lang.NoClassDefFoundError: com/something/myagent/MyAgentPrinter
    at sun.security.ssl.Handshaker.printLogLine(Handshaker.java)
    at sun.security.ssl.Handshaker.calculateKeys(Handshaker.java:1160)
    at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:292)

有没有办法将该类[MyAgentPrinter]添加到应用程序的类路径中?

共有1个答案

戴化
2023-03-14

您的代理的jar文件已经添加到类路径中,如java所指定。lang.instrument软件包文档:

代理类将由系统类加载器加载(请参见ClassLoader.getSystemClassLoader)。这是类加载器,它通常加载包含应用程序main方法的类。premain方法将在与应用程序main方法相同的安全性和类加载器规则下运行。

这就是为什么Javassist在转换字节码时可以找到代理的类。

问题似乎是你正在改造一个太阳** 可能由引导加载程序或扩展加载程序加载的类。标准的类加载委托是
应用程序加载器→ 扩展装载机→ 引导加载程序,因此应用程序加载程序可用的类对扩展或引导加载程序加载的类不可用。

因此,要使它们对所有类都可用,必须将代理的类添加到引导加载程序:

public class MyAgent {
    public static void premain(String agentArgs, Instrumentation inst) throws IOException {
        JarURLConnection connection = (JarURLConnection)
            MyAgent.class.getResource("MyAgent.class").openConnection();
        inst.appendToBootstrapClassLoaderSearch(connection.getJarFile());

        // proceed
    }
}

在任何其他操作之前,即在加载要提供给仪表化代码的类之前,这样做是至关重要的。这意味着代理类本身,即包含premain方法的类不能被仪表化代码访问。代理类也不应该直接引用MyAgentPrinter,以避免意外的提前加载。

一个更可靠的方法是在Agent jar的清单中添加一个Boot-Class-Path条目,请参阅包留档的清单属性部分,以便在Agent启动之前添加该条目。但是之后,jar文件的名称不得更改。

 类似资料:
  • 问题内容: 如何在netbeans项目的类路径中添加文件夹(例如,包含arts的资源文件夹)?我设法通过编辑项目的NB生成的jar文件(即其MANIFEST.MF文件+手动复制资源)来手动完成此操作,但是应该有一种方法可以告诉netbeans并注意资源,不是吗? 文件夹结构如下所示: 我不想将艺术品包装到罐子里,因为我希望艺术品可以轻松更换。如果我将art文件夹添加到src文件夹,则NB可以正常编

  • 我希望title本身是描述性的,但要明确的是,我试图在greeting-service.jar中包含(即,error-handling-service.jar)。在构建之后,我在新项目(即TestApplication)中包含了greeting-service.jar,但在执行我得到的TestApplication时(顺便说一句,TestApplication不是一个gradle项目) BaseE

  • 我正在尝试使用第三方应用程序来测试Liberty Server18.0,并尝试在Linux上向Liberty Server类路径添加一个库。这个库名为:“com.ibm.websphere.javaee.security.1.0_1.0.21.jar”,它位于Liberty服务器的“/wlp/dev/api/sec”下。 我看得出来,它从来没上过子弹。我如何将这个jar添加到我的defaultSe

  • 我有一个批处理文件,它使用依赖于tools.jar(来自JDK)的maven运行java类。 例如: mvn-f.\pom.xml-e exec:java-dfile.encoding=“utf-8”-dexec.mainclass=MyClass-dexec.args=“%1%2%3%4%5%6%7%8%9”-dexec.classpathscope=runtime 我的程序使用JDK中的too

  • 我正在尝试运行一个由其他人创建的已经存在的eclipse项目。 在将其导入eclipse并尝试作为->Java应用程序运行之后,它失败了,因为它在bin/resources中找不到.properties文件 我打印出eclipse使用的类路径 果然,它包括bin和所有lib/*.jars,但不包括bin/resources。将.properties文件复制到bin中可以使程序正常工作,但我想了解如

  • 问题内容: 我正在尝试开发一个Java代理,它将借助asm-4来检测代码。现在,我陷入了一个非常基本的问题,javaagent的类加载器看不到asm依赖关系,因此失败。我是否必须提供一个jar- with- dependencies(又名maven构建插件),其中包含代理所需的所有类,或者是否有另一种方法可将类添加到Java代理?直接在类路径中引用jar asm-all.jar并没有帮助。最初,构