Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在程序启动后启动Java代理_Java_Javaagents - Fatal编程技术网

在程序启动后启动Java代理

在程序启动后启动Java代理,java,javaagents,Java,Javaagents,在虚拟机从同一个VM中启动之后,是否可以插入javaagent 比如说,我们在jar myagent.jar中有一个代理,它具有适当的元数据设置,并且已经实现了一个agentmain方法。现在,用户程序调用一个API调用,这将导致插入代理,以便重新定义类 可以这样做吗?如何做?您应该能够在Java 6中这样做,请参阅“VM启动后启动代理”一章 编辑:也许在Java 5中已经有可能了,只是javadocs没有明确提到,有一个关于如何编写代理以及如何动态启动代理的好例子。是的,您只需将JVM进程ID

在虚拟机从同一个VM中启动之后,是否可以插入javaagent

比如说,我们在jar myagent.jar中有一个代理,它具有适当的元数据设置,并且已经实现了一个agentmain方法。现在,用户程序调用一个API调用,这将导致插入代理,以便重新定义类


可以这样做吗?如何做?

您应该能够在Java 6中这样做,请参阅“VM启动后启动代理”一章


编辑:也许在Java 5中已经有可能了,只是javadocs没有明确提到,

有一个关于如何编写代理以及如何动态启动代理的好例子。

是的,您只需将JVM进程ID传递给
VirtualMachine.attach(String pid)
方法,然后加载代理jar。JDK_HOME/lib/tools.jar文件中提供了
VirtualMachine
类。以下是如何在运行时激活代理的示例:

public static void attachGivenAgentToThisVM(String pathToAgentJar) {
  try {                                                                               
    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();                                                   
    String pid = nameOfRunningVM.substring(0, nameOfRunningVM.indexOf('@'));                                                   
    VirtualMachine vm = VirtualMachine.attach(pid);                                                                            
    vm.loadAgent(pathToAgentJar, "");
    vm.detach();   
  } catch (Exception e) {
    e.printStackTrace();
  }
}                                                                                                            

遇到同样的问题后,我找到了一个更全面的解决方案

ByteBuddy尝试动态加载其java代理:

在当前运行的Java虚拟机上安装代理。不幸的是,这并不总是有效的。Java代理的运行时安装受以下支持:

  • JVM版本9+:对于至少版本9的Java VM,附件API被移动到一个模块中,如果{@code jdk.attach}模块可用于Byte Buddy,则运行时安装是可能的,而Byte Buddy通常仅可用于jdk附带的VM
  • OpenJDK/Oracle JDK/IBM J9 versions 8-:HotSpot的安装仅在与JDK捆绑在一起并且需要与VM捆绑在一起的{@code tools.jar}时才可能进行,而VM通常仅适用于JVM的JDK版本
  • 当运行Linux并包含可选的JUnitSocket本机公共依赖项时,Byte Buddy模拟Unix套接字连接以连接到目标VM

  • 但是,它没有指定方法调用是什么。然而,进一步研究它会((URLClassLoader)ClassLoader.getSystemClassLoader()).addURL(..)其中添加的URL指向myagent.jar,导致调用agentmain?这是一般的Java 6还是只使用热点?@Paul:我没有尝试过,所以我不能说它是否这样工作,但它似乎合理。但是,您必须通过反射调用addURL,因为它是受保护的。类似于:URLClassLoader sysloader=(URLClassLoader)ClassLoader.getSystemClassLoader();类sysclass=URLClassLoader.Class;试试{Method Method=sysclass.getDeclaredMethod(“addURL”,参数);Method.setAccessible(true);Method.invoke(sysloader,新对象[]{yourURL});}这不是一个自包含的教程,true。但对于高级Java开发人员来说,这是一个很好的例子。一、 就我个人而言,我对这个例子没有任何问题。链接断了。我能在Wayback机器上找到它的存档:这个链接不再起作用了。你应该复制内容并粘贴到这里。回程链接应该suffice@AlanCabrera我正在使用JDK1.8。我曾经尝试过oracle和openjdk,但我永远无法连接到jvm。该尝试在目标jvm中导致线程转储,并在注入jvm上失败,如com.sun.tools.attach.AttachNotSupportedException:无法打开套接字文件:目标进程未响应或热点VM未在sun.tools.attach.LinuxVirtualMachine上加载。(LinuxVirtualMachine.java:106)在com.sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63)在com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208)在Main.Main(Main.java:15)感谢您的回答。但是当我尝试同样的方法时,我得到了一个异常**com.sun.tools.attach.AgentLoadException:Agent JAR找不到或没有Agent Class属性**我怀疑这是一个依赖性问题,这里如何在maven中解决:(“运行时动态加载javaagent”部分)@11101101b我使用的是jdk 1.8。我曾经尝试过oracle和openjdk,但我永远无法连接到jvm。该尝试在目标jvm中导致线程转储,并在注入jvm上失败,如com.sun.tools.attach.AttachNotSupportedException:无法打开套接字文件:目标进程未响应或热点VM未在sun.tools.attach.LinuxVirtualMachine上加载。(LinuxVirtualMachine.java:106)在com.sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63)在com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208)在Main.Main(Main.java:15)我已经在CentOS和Ubuntu上试过了。两者都以同样的方式失败了它需要tools.jar,是否值得在类路径中添加tools.jar。(使用Java8)