gpt4 book ai didi

java - 使用 Java 代理将类添加到类路径

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:02:39 26 4
gpt4 key购买 nike

我正在使用 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] 添加到应用程序的类路径中吗?

最佳答案

您的代理的 jar 文件已经添加到类路径中,如 the java.lang.instrument package documentation 所指定的那样:

The agent class will be loaded by the system class loader (see ClassLoader.getSystemClassLoader). This is the class loader which typically loads the class containing the application main method. The premain methods will be run under the same security and classloader rules as the application main method.

这就是Javassist在你转换字节码的时候能找到Agent类的原因。

问题似乎是您正在转换一个 sun.** 类,它可能由引导加载程序或扩展加载程序加载。标准的类加载委托(delegate)是
application loader → extension loader → bootstrap loader,因此应用程序加载器可用的类不适用于扩展或引导加载器加载的类。

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

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

在任何其他操作之前执行此操作至关重要,即在加载要提供给检测代码的类之前。这意味着 Agent 类本身,即包含 premain 方法的类不能被检测代码访问。 Agent 类也不应直接引用 MyAgentPrinter 以避免意外提前加载。

一个更可靠的方法是在 Agent jar 的 list 中添加一个 Boot-Class-Path 条目,参见 the “Manifest Attributes” section of the package documentation ,以便在代理启动之前添加该条目。但是之后,jar 文件的名称不得更改。

关于java - 使用 Java 代理将类添加到类路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46832523/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com