2016-08-15 3 views
5

기본적으로 JVM에서로드 한 모든 클래스를 나열하는 내용을 작성하려고합니다. 내가 작성한 것은 작동하지만, 작동중인 jvm에서만 작동합니다. 다른 JVM에 동적으로 삽입 할 Java 에이전트를 만들었지 만 실제로 주입하는 방법을 알지 못했습니다. 이 에이전트를 다른 JVM으로 실제로 보내려면 어떻게해야합니까? 가능합니까?Java - Java 에이전트를 실행중인 jvm에 삽입

답변

-1

당신이 작성한 내용을 보지 않고 도움을주기는 어렵지만 이것은 Java 프로그래밍 언어 코드를 계측하는 데 필요한 서비스를 제공하는 java.lang.instrument 패키지의 계측 인터페이스 (public interface Instrumentation) 클래스라는 것이 있음을 알리는 것입니다. .

이 클래스에서 제공하는 메서드 중 하나는로드되는 모든 클래스가 들어있는 배열을 반환하는 getInitiatedClasses입니다. 문서에

찾는 here

getInitiatedClasses

클래스 [] getInitiatedClasses (클래스 로더 로더)
는 로더 기동 로더 모든 클래스의 배열을 반환. 제공된 로더가 null 인 경우 부트 스트랩 클래스 로더에 의해 시작된 클래스가 반환됩니다.

매개 변수 : 로더 - 시작 클래스 목록 반환 반환되는 로더 : 아무도

가없는 경우 로더가 기동 로더, 길이 제로의 인 모든 클래스를 포함한 배열
+0

나는이 알고 있는데 여기

원격 JVM에 의해로드 된 모든 클래스를 나열하는 샘플 도구입니다. 문제는 jar가 이미 실행 중이고 javaagent를 연결해야한다는 것입니다. – Stoud

3

HotSpot Attach API으로 요원을 주입 할 수 있습니다.
클래스 경로에 $JAVA_HOME/lib/tools.jar과 함께 다음 스 니펫을 실행하십시오. 동적 연결 지원하기 위해, 자바 에이전트가 agentmain 방법 MANIFEST.MF에서 Agent-Class 속성을 가져야한다고

$ jattach PID load instrument false /path/to/agent.jar 

참고 :

VirtualMachine vm = VirtualMachine.attach(PID); 
    try { 
     vm.loadAgent(agentJar); 
    } finally { 
     vm.detach(); 
    } 

또는 당신은 내 명령 줄에 jattach 유틸리티를이 작업을 수행 할 수 있습니다.

+0

상담원에게 약간의 문제가 있습니다. 계측 에이전트를 대상 JVM과 별도로 팩하는 것이 가장 표준적인 방법이라고 가정합니다. 내'agentmain()'이 호출 될 때 Class.forName ("pkg.name")'을 호출하여 JVM 클래스를 찾으려고 시도했지만 항상 NoClassDefFoundError를 반환합니다. 나는 여기에 질문을 올렸다. (https://stackoverflow.com/questions/46523055/using-class-forname-in-java-instrumentation-agent?noredirect=1#comment80003396_46523055); 에이전트가 VM에 연결되어 있어도 해당 클래스를 참조 할 수없는 이유는 약간 혼란 스럽습니다. – ha9u63ar

6

동적 에이전트는 대상 VM 내의 첨부시 실행되는 agentmain(String, Instrumentation) 메서드를 선언해야합니다. tools.jar 종속성은 (Java 9까지) JDK에만 포함되지만 JRE에는 포함되지 않습니다. 그러나 에이전트 프로그램을 JDK와 함께 번들로 묶어 JVM에 연결할 수 있습니다.

가장 큰 낙오는 API가 다른 VM에 따라 다르다는 것입니다. 그러나 다른 VM에 대해 다른 구현을 포함하는 byte-buddy-agent과 같은 라이브러리를 사용할 수 있습니다.이 ID 내-ID와 Java 프로세스에 my.jar에 포함 된 에이전트를 연결합니다

ByteBuddyAgent.attach("my.jar", "my-pid"); 

: 첨부 파일이 수행 할 것입니다.

+0

pid가 tasklist에 표시된 것과 동일할까요? – Stoud

+0

예. OS 프로세스 ID입니다. –

+0

이 작업을 시도했는데 테스트 결과 내 agentmain 메서드가 호출되지 않습니다. – Stoud

3

the comment에서 알 수있는 한, 다른 Java 프로세스 내에서 원격 JVM을 검사 할 수있는 무언가에 관심이 있습니다. 이 경우 자바 에이전트가 아닌 Serviceability Agent이 필요합니다.

을 사용하면 다른 JVM 프로세스에 연결하고, 메모리를 읽고, VM 구조를 재구성하고, 반사와 같은 방식으로 원격 객체를 검사 할 수 있습니다.

import sun.jvm.hotspot.runtime.VM; 
import sun.jvm.hotspot.tools.Tool; 

public class ListRemoteClasses extends Tool { 

    public static void main(String[] args) { 
     new ListRemoteClasses().execute(args); 
    } 

    @Override 
    public void run() { 
     VM.getVM().getSystemDictionary().classesDo(klass -> { 
      String className = klass.getName().asString().replace('/', '.'); 
      System.out.println(className); 
     }); 
    } 
} 

방법을 실행하기 :

java -cp $JAVA_HOME/lib/sa-jdi.jar:. ListRemoteClasses PID 
관련 문제