1

jdk1.6を使用しています。実行時にjarを正常にロードしました。コードは次のとおりです。

vm = VirtualMachine.attach(vid);
vm.loadAgent(agentPath);

ここで、実行時にこのエージェントをアンロードしたいと思います。それを行うための API DOC はありません。誰かアドバイスをくれませんか?ありがとう。

編集

その他のコード

GlobalVariables.vm = VirtualMachine.attach(vid);

// Check to see if transformer agent is installed
if(!GlobalVariables.vm.getSystemProperties().contains("demo.agent.installed")) {
    System.out.println("Load agent");

    GlobalVariables.vm.loadAgent(agentPath); 

}

GlobalVariables.connectorAddress = GlobalVariables.vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress", null);
if(null == GlobalVariables.connectorAddress) {
    // It's not, so install the management agent
    String javaHome = GlobalVariables.vm.getSystemProperties().getProperty("java.home");
    File managementAgentJarFile = new File(javaHome + File.separator + "lib" + File.separator + "management-agent.jar");
    GlobalVariables.vm.loadAgent(managementAgentJarFile.getAbsolutePath());
    System.out.println("Load Management agent");
    GlobalVariables.connectorAddress = GlobalVariables.vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress", null);
    // Now it's installed
}

// Now connect and transform the classnames provided in the remaining args.
//JMXConnector connector = null;
try {
    // This is the ObjectName of the MBean registered when loaded.jar was installed.
    //ObjectName on = new ObjectName("transformer:service=DemoTransformer");
    GlobalVariables.on = new ObjectName("transformer:service=DemoTransformer");
    // Here we're connecting to the target JVM through the management agent
    GlobalVariables.connector = JMXConnectorFactory.connect(new JMXServiceURL(GlobalVariables.connectorAddress));
    GlobalVariables.server = GlobalVariables.connector.getMBeanServerConnection();
    System.out.println("MBean Server connection...");

    // Call transformClass on the transformer MBean
    GlobalVariables.server.invoke(GlobalVariables.on, "transformClass", new Object[]{className, args}, new String[]{String.class.getName(), String.class.getName()});

} catch (Exception ex) {
    ex.printStackTrace(System.err);
} finally {
    if(GlobalVariables.connector!=null) try { GlobalVariables.connector.close(); } catch (Exception e) {}
    GlobalVariables.vm.detach();
    System.out.println("Has disconnected");
}

その時私は何をしましたか

上記のコードを再度実行して、これら 2 つのエージェントを再度読み込みます。しかし、エラーが発生しました。

エラー

現在の vm のエラー

com.sun.tools.attach.AgentInitializationException: Agent JAR loaded but agent failed to initialize
    at sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java:103)
    at com.sun.tools.attach.VirtualMachine.loadAgent(VirtualMachine.java:508)
    at faultinjectionaction.AttachClass.attachAgent(AttachClass.java:111)
    at org.apache.jsp.fjstep3_jsp._jspService(fjstep3_jsp.java:350)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:619)

ターゲット vm のエラー

Exception in thread "Attach Listener" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:323)
        at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:348)
Caused by: javax.management.InstanceAlreadyExistsException: transformer:service= DemoTransformer
        at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:453)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.internal_addObject(DefaultMBeanServerInterceptor.java:1484)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:963)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:917)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:312)
        at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:482)
        at faultinjectionagent.AgentMain.agentmain(AgentMain.java:28)
        ... 6 more

標的

エラーなしで同じ仕事をすること。毎回仕事が終わったらエージェントをアンロードする必要があると思います。しかし、それらのエージェントをアンロードできませんでした。

GlobleVariables の編集

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import com.sun.tools.attach.VirtualMachine;

public class GlobalVariables{
    public static MBeanServerConnection server;
    public static ObjectName on;
    public static JMXConnector connector = null;
    public static String connectorAddress = null;
    public static VirtualMachine vm;
}
4

1 に答える 1

2

エージェントをアンロードするとはどういう意味ですか? ドキュメントに暗黙的に記載されているように、クラスをアンロードすることはできません。

指定された JAR ファイルが (ターゲット仮想マシンの) システム クラス パスに追加されます。

これを回避する唯一の方法は、カスタム クラス ローダー マジックかもしれませんが、それはお勧めしません。

更新:拡張された質問を見た後、あなたの問題は実際には別のものだと思います。ある時点で、あなたは呼び出しています

JMXConnectorFactory.connect(new JMXServiceURL(GlobalVariables.connectorAddress))

を作成するためにJMXConnector。あなたのGlobalVariables.server.invoke呼び出しの中で、MBean を によって登録していると思いますnew ObjectName("transformer:service=DemoTransformer")。この名前は一意である必要があり、コードを 2 回目に実行するときに、この名前は で提案されているとおりに既に使用されていjavax.management.InstanceAlreadyExistsException: transformer:service= DemoTransformerます。あなたがする必要があったのは:

  • MBean を再度登録するときに、別の名前を選択してください。
  • MBeanServerConnection.close(new ObjectName("transformer:service=DemoTransformer"))名前を再度使用できるようにするために、リモート JVM からデタッチする前に呼び出します。

デタッチによって、リモート マシンのすべての状態がリセットされたと思われるかもしれません。しかし、これは真実ではありません。名前を付けて MBean を追加しましたが、これを再度実行しようとしました。このエラーは、同じキーを持つ 2 つの値をマップに追加したかのように理解できます。ただし、マップ以外では、値をオーバーライドすることはありませんが、上記の例外が発生します。

ちなみに、JMXConnector.closeリモートサーバーへの接続が不要になった場合は、明示的に呼び出す必要があります。

PS:この記事は面白いかもしれません。

更新 2 : チャットで議論した後、MBean の名前付けの競合を解決した後、これが問題の原因だと思います。

Java エージェントが 2 回目にロードされるとき、エージェントに付属するクラス ( で表されmanagementAgentJarFileます) は、ターゲット JVM にすでにロードされています。つまり、クラス初期化子が再度実行されることはなく、static変数によって表される状態の変更は引き続き表されます。さらに、同じ名前で実装が変更されたクラスをロードすることはできません。これによりLinkageErrors が発生し、エージェントのロードが失敗します。解決策は、エージェントが自分自身を負わせることができないような状態を回避staticし、エージェントごとに個別の名前空間を作成することです。それ以外の場合は、カスタム クラス ローダーを使用してエージェント クラスをアンロードできます。この問題の詳細については、多くの場所とここで見つけることができます。

于 2013-11-27T10:21:06.417 に答える