我正在使用jetty-alpn-agent
为我的项目添加 ALPN 支持,但我能找到的只是有关如何从.m2
文件夹中运行它的说明,这使我需要部署两个 jar:s 而不仅仅是我的一个 uber-jar,使其更少便携的。
是否可以为 -javaagent 开关指定 jar 内的位置?
我正在寻找类似的东西java -javaagent:my.jar!/javaagents/jetty-alpn-agent-2.0.0.jar -jar myjar.jar
,但这似乎不起作用。
我正在使用jetty-alpn-agent
为我的项目添加 ALPN 支持,但我能找到的只是有关如何从.m2
文件夹中运行它的说明,这使我需要部署两个 jar:s 而不仅仅是我的一个 uber-jar,使其更少便携的。
是否可以为 -javaagent 开关指定 jar 内的位置?
我正在寻找类似的东西java -javaagent:my.jar!/javaagents/jetty-alpn-agent-2.0.0.jar -jar myjar.jar
,但这似乎不起作用。
根据java.lang.instrumentation文档,这可能是可能的。
如果实现允许它jetty-alpn-agent.jar
必须是系统类路径的一部分。因此,您必须my.jar
像任何其他应用程序库一样将其包含在您的应用程序库中。
虚拟机启动后启动代理
实现可以提供一种机制来在 VM 启动后的某个时间启动代理。关于如何启动的细节是特定于实现的,但通常应用程序已经启动并且它的 main 方法已经被调用。如果实现支持在 VM 启动后启动代理,则适用以下情况:
代理 JAR 的清单必须包含属性 Agent-Class。该属性的值是代理类的名称。
代理类必须实现公共静态 agentmain 方法。
系统类加载器 (ClassLoader.getSystemClassLoader) 必须支持将代理 JAR 文件添加到系统类路径的机制。
代理 JAR 附加到系统类路径。这是通常加载包含应用程序主方法的类的类加载器。代理类被加载,JVM 尝试调用 agentmain 方法。JVM 首先尝试在代理类上调用以下方法:
public static void agentmain(String agentArgs, Instrumentation inst);
如果代理类未实现此方法,则 JVM 将尝试调用:
public static void agentmain(String agentArgs);
当使用命令行选项启动代理时,代理类也可能有一个 premain 方法。在 VM 启动后启动代理时,不会调用 premain 方法。
代理通过 agentArgs 参数传递其代理选项。代理选项作为单个字符串传递,任何额外的解析都应该由代理自己执行。
agentmain 方法应该执行启动代理所需的任何必要初始化。启动完成后,该方法应返回。如果无法启动代理(例如,因为无法加载代理类,或者因为代理类没有符合的 agentmain 方法),则 JVM 不会中止。如果 agentmain 方法抛出未捕获的异常,它将被忽略。
PS:我从来没有试过这个。请让我知道它是否有效。
您可以通过将 premain 类写入 fat jar 的清单来模拟以前的代理。然后,只需通过javaagent和jar参数添加您的 fat jar。
无法避免这种情况,因为检测 API 非常强大,并且允许避免安全管理器提供攻击的入口点。但是,您可以在 JDK 或 Java 9 VM 上进行自连接。byte-buddy-agent库为此提供了现成的依赖项。这样,您可以在获取检测实例后手动调用您的 premain 方法。