2011-03-04 10 views
11

Java 호스트 6 및 로컬 호스트에서 실행중인 JVM 목록 및 해당 사양 (예 : Java 버전, 실행중인 스레드 등)을 가져 오는 방법은 무엇입니까?로컬 호스트에서 실행중인 JVM 목록

Java API가 이러한 기능을 제공합니까? 이 일을 할 수있는 자바 라이브러리가 있습니까?

+1

VisualVM과 그래서 방법이 있어야합니다 그것을 할 수있다, 아마 쉬운 일이지만 . – biziclop

답변

14

. 비록 어떤 일반적인 Java API도 알지 못합니다. 그러나 JConsole은 사용자가 요청한 것을 수행 할 수 있으므로 소스를 살펴 보았습니다. 꽤 무서웠지만 주변을 둘러 보면서 jVisualVM 클래스에 대한 참조를 발견했습니다. Java 클래스는 Java 6 이상을 지정하면 볼 수 있습니다. 여기 내가 찾은 것이 있습니다 :

클래스는 모두 sun.tools입니다. 따라서 처음에는 JVM과 함께 제공되는 jconsole.jar을 찾아야합니다 (물론 Sun JVM을 가정 함). 클래스 경로에 추가하십시오. 그런 다음 활성 VM을 더러운 빠른-N-목록을 같이 가지고 할 수 있습니다 : 당신이 당신의 JVM에 대한 참조를했으면

public static void main(final String[] args) { 
    final Map<Integer, LocalVirtualMachine> virtualMachines = LocalVirtualMachine.getAllVirtualMachines(); 
    for (final Entry<Integer, LocalVirtualMachine> entry : virtualMachines.entrySet()) { 
     System.out.println(entry.getKey() + " : " + entry.getValue().displayName()); 
    } 
} 

, 당신은 그들이 Attach API을 사용하여 통신 할 수 있습니다.

+0

매우 흥미 롭습니다! 또한이 솔루션을 찾았습니다. http://download.oracle.com/javase/6/docs/technotes/guides/management/agent.html#gdhkz. JAVA_HOME/lib의 tools.jar을 사용합니다 (classpath에 추가해야 함). – fsarradin

8

jps\jdk\bin 디렉토리에는 실행중인 Java 프로세스 목록이 인쇄되지만 스펙은 인쇄되지 않습니다. 일부 실행 조건을 사용할 수 있습니다 : 당신은 jps, JVM을 함께 배포 명령 줄 도구를 사용할 수 있습니다

C:\Java\jdk1.6.0_23\bin>jps -mlv 
4660 -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -XX:MaxPermSize=256m 
6996 sun.tools.jps.Jps -mlv -Dapplication.home=C:\Java\jdk1.6.0_23 -Xms8m 
1

Java 6에 대해서는 잘 모르겠지만 명령 줄에서 jconsole을 실행하면됩니다.

또한, 당신이 * nix에서 스크립트 플랫폼에있는 경우이 같은 명령을 실행할 수 있습니다 :

ps aux | grep java 

행운을 빕니다!

+6

'| grep java'를 의미합니까? –

1

또한 jps에는 모든 Java 프로세스의 스택 추적을 인쇄 할 수있는 jstack 도구가 있습니다. 출력의 시작에는 VM 버전이 포함되어 있으며 스택 추적이있는 스레드 목록이 제공됩니다.

Java Management Beans API (javax.management.*java.lang.management)를 기반으로 구현되는 3 가지 이유가 있으므로 자신의 프로그램에서이 작업을 수행하는 방법에 대해 자세히 알아보십시오.


편집 : 다음은 관리 용으로 documentation index입니다. 특히 흥미로운 점은 Monitoring and Management Using the JMX API입니다.

(그리고 네, 그것은 동일한 시스템에서, 심지어 그들이 적절한 인터페이스를 노출하는 경우 원격 시스템들에 대한 다른 사람을 위해 또한 자신의 VM에 대한뿐만 아니라 작동합니다.)

+0

'java.lang.management'에는 클래스가 포함되어 있지만 현재 실행중인 JVM을 검사 할 수 있으며 다른 컴퓨터와 동일한 컴퓨터는 검사 할 수 없다고 생각합니다. –

+0

나는 고쳐졌다! 이것은 좋은 물건입니다. –

+0

링크 감사합니다. – fsarradin

0

를 내가 아는 한 jps는 자신이 속한 jvm을 사용하여 시작한 프로세스 목록을 제공합니다. 여러 JDK가 설치되어 있다면 도움이 될 것이라고 생각하지 않습니다. 모든 Java 프로세스 목록을 원하면 "ps -ef | grep java"를 사용해야합니다. JVsualVM이 특정 호스트에서 실행중인 모든 Java 프로세스를 식별 할 수없는 경우가 많습니다. 요구 사항이 JVM 실행 프로세스에만 해당되면 위의 제안이 적용됩니다.

1

기본적으로 JPS가 수행하는 작업은 다음과 같습니다. /tmp/hsperfdata_foo/ 여기서 foo는 JVM을 실행하는 사용자입니다.

알 수없는 이유로 JVM이 종료되었을 때 파일이 삭제되지 않는 경우가 있습니다. 당신의 PID와의 JVM을 실행 단지 목록이 필요하면

PerfDataFile.java

LocalVmManager

1

이 나를 위해 작동합니다 :

package my.code.z025.util; 

import java.util.LinkedList; 
import java.util.List; 
import java.util.Set; 

import sun.jvmstat.monitor.HostIdentifier; 
import sun.jvmstat.monitor.MonitorException; 
import sun.jvmstat.monitor.MonitoredHost; 
import sun.jvmstat.monitor.MonitoredVm; 
import sun.jvmstat.monitor.MonitoredVmUtil; 
import sun.jvmstat.monitor.VmIdentifier; 

/** 
* Get list of all local active JVMs 
*/ 
public class ActiveJavaVirtualMachineExplorer { 

    /** 
    * Represents successfully captured active java virtual machine 
    */ 
    public static class ActiveVm { 
     private int pid; 
     private String name; 
      ... shortened ... 
    } 

    /** 
    * Represents unsuccessfully captured active java virtual machine, a failure. 
    * Keep cause exception. 
    */ 
    public static class FailedActiveVm extends ActiveVm { 
     private Exception cause; 
     ... shortened ... 
    } 

    /** 
    * Get list of all local active JVMs. 
    * <p> 
    * Returns something like: 
    * ActiveVm [pid=7992, name=my.code.z025.util.launch.RunHttpServer] 
    * ActiveVm [pid=6972, name=] 
    * ActiveVm [pid=8188, name=my.code.z025.util.launch.RunCodeServer] 
    * ActiveVm [pid=4532, name=org.eclipse.jdt.internal.junit.runner.RemoteTestRunner] 
    * The pid=6972 must be Eclipse. So this approach is not water tight. 
    */ 
    public static List<ActiveVm> getActiveLocalVms() { 
     List<ActiveVm> result = new LinkedList<ActiveVm>(); 
     MonitoredHost monitoredHost; 
     Set<Integer> activeVmPids; 
     try { 
      monitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String) null)); 
      activeVmPids = monitoredHost.activeVms(); 
      for (Integer vmPid : activeVmPids) { 
       try { 
        MonitoredVm mvm = monitoredHost.getMonitoredVm(new VmIdentifier(vmPid.toString())); 
        result.add(new ActiveVm(vmPid.intValue(), MonitoredVmUtil.mainClass(mvm, true))); 
        mvm.detach(); 
       } catch (Exception e) { 
        result.add(new FailedActiveVm(vmPid.intValue(), e)); 
       } 
      } 
      return result; 
     } catch (java.net.URISyntaxException e) { 
      throw new InternalError(e.getMessage()); 
     } catch (MonitorException e) { 
      throw new InternalError(e.getMessage()); 
     } 
    } 
} 

응용 프로그램을 여기에

소스 코드에 대한 링크입니다 이와 같이 탐지 할 수있는 특수 명령 행 매개 변수를 사용하여 실행할 필요는 없습니다. JMX를 활성화 할 필요가 없습니다.

모든 JVM 응용 프로그램이 잘 작동하는 것은 아닙니다. Eclipse의 경우 PID 만 표시되지만 클래스 이름이나 명령 줄은 표시되지 않습니다.

tool.jar을 클래스 경로에 추가해야합니다.이 패키지에는 sun.jvmstat.* 패키지가 포함되어 있습니다. tool.jar은 JDK의 일부입니다. JDK/OS의 일부 변종에서는 기본적으로 classpath에 있으며 일부는 추가해야합니다. Maven 종속성을 사용하는 것은 다소 까다 롭습니다. systemPath가 필요합니다.

목록이 더 필요하면 Paŭlo Ebermann - Monitoring and Management Using the JMX API 링크를 확인하십시오.

VirtualMachine vm = VirtualMachine.attach(pid); 

여기서 PID는 목록에서 가져옵니다. 그런 다음 (예상치 못한) Java (또는 JVM) 응용 프로그램에 에이전트를 삽입하십시오.

vm.loadAgent(agentJarLibraryFullPath); 

그런 다음 JMXConnector를 통해 상담원과 통신하십시오. 상담원이 모든 통계를 수집 할 수 있습니다. 나는 그것을 개인적으로 시도하지 않았다. 이런 식으로 런타임 코드를 계측 (수정) 할 수도 있습니다. 프로파일 러는이를 사용합니다.

4

jconsole.jar을 사용하지 않고 실제로 Attach API을 사용하여 JVM 목록을 가져올 수 있습니다.

다음은 로컬에서 실행되는 JVM 목록을 얻고, 일부 속성을 가져오고, JMX를 통해 각각에 연결하고, 해당 연결을 통해 추가 정보를 얻는 방법을 보여줍니다.

// ... 

import com.sun.tools.attach.*; 
import javax.management.*; 

// ... 

    List<VirtualMachineDescriptor> descriptors = VirtualMachine.list(); 
    for (VirtualMachineDescriptor descriptor : descriptors) { 
     System.out.println("Found JVM: " + descriptor.displayName()); 
     try { 
      VirtualMachine vm = VirtualMachine.attach(descriptor); 
      String version = vm.getSystemProperties().getProperty("java.runtime.version"); 
      System.out.println(" Runtime Version: " + version); 

      String connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); 
      if (connectorAddress == null) { 
       vm.startLocalManagementAgent(); 
       connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); 
      } 

      JMXServiceURL url = new JMXServiceURL(connectorAddress); 
      JMXConnector connector = JMXConnectorFactory.connect(url); 
      MBeanServerConnection mbs = connector.getMBeanServerConnection(); 

      ObjectName threadName = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME); 
      Integer threadCount = (Integer)mbs.getAttribute(threadName, "ThreadCount"); 
      System.out.println(" Thread count: " + threadCount); 
     } 
     catch (Exception e) { 
      // ... 
     } 
    } 

가능한 MXBean의 목록이 here입니다. 일반적으로 JMX에 대한 자세한 내용은 입니다.이 질문에 대한 답변은 another answer입니다. 위의 일부 코드는 두 링크에서 제공됩니다.

는 : 나를 위해 적어도, 나는 이것이 실행을위한 부트 스트랩 클래스 경로에 tools.jar를 추가했다 :

$ java -Xbootclasspath/a:${JAVA_HOME}/lib/tools.jar -jar <jar> 
+0

LocalVirtualMachine은 Java8에서 사용할 수있는 longuer가 아니며, 이제이 답변이 올바른 것입니다. – loicmathieu

관련 문제