기본적으로 JVM에서로드 한 모든 클래스를 나열하는 내용을 작성하려고합니다. 내가 작성한 것은 작동하지만, 작동중인 jvm에서만 작동합니다. 다른 JVM에 동적으로 삽입 할 Java 에이전트를 만들었지 만 실제로 주입하는 방법을 알지 못했습니다. 이 에이전트를 다른 JVM으로 실제로 보내려면 어떻게해야합니까? 가능합니까?Java - Java 에이전트를 실행중인 jvm에 삽입
답변
당신이 작성한 내용을 보지 않고 도움을주기는 어렵지만 이것은 Java 프로그래밍 언어 코드를 계측하는 데 필요한 서비스를 제공하는 java.lang.instrument
패키지의 계측 인터페이스 (public interface Instrumentation
) 클래스라는 것이 있음을 알리는 것입니다. .
이 클래스에서 제공하는 메서드 중 하나는로드되는 모든 클래스가 들어있는 배열을 반환하는 getInitiatedClasses
입니다. 문서에
찾는 here
getInitiatedClasses
클래스 [] getInitiatedClasses (클래스 로더 로더)
는 로더 기동 로더 모든 클래스의 배열을 반환. 제공된 로더가 null 인 경우 부트 스트랩 클래스 로더에 의해 시작된 클래스가 반환됩니다.매개 변수 : 로더 - 시작 클래스 목록 반환 반환되는 로더 : 아무도
가없는 경우 로더가 기동 로더, 길이 제로의 인 모든 클래스를 포함한 배열
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 유틸리티를이 작업을 수행 할 수 있습니다.
상담원에게 약간의 문제가 있습니다. 계측 에이전트를 대상 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
동적 에이전트는 대상 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");
: 첨부 파일이 수행 할 것입니다.
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
나는이 알고 있는데 여기
원격 JVM에 의해로드 된 모든 클래스를 나열하는 샘플 도구입니다. 문제는 jar가 이미 실행 중이고 javaagent를 연결해야한다는 것입니다. – Stoud