Right now do !

[JAVA] 프로그램 코드내에서 다른 VM (java process) 확인하는 방법

by 지금당장해

프롤로그

필자는 요즘 java web application server를 만들고 있다. 그렇다 톰켓 같은거... 베타 버전을 배포해서 몇 몇 사용자로 부터 요구사항이 들어왔다. jps 명령으로 확인해봐도 되지만 JRE 만 깔려 있어 jps를 쓸수 없는 경우, 실행된지 모르고 또 실행한 경우가 있다는거다. 서버 프로세스의 실행을 감지하여 만약 같은 서버가 동작 중이면 실행한 서비스를 중단 시킬수 있냐는 것이다. 이번 글은 해당 요구사항을 해결하기 위한 필수 요소인 현재 시스템내에 실행 중인 VM 리스트를 구하는 방법에 대해 다루려 한다.

 

bash shell에서 jps - 실행 결과

본론

참조

필자가 프로그램 코드에서 사용한 라이브러리는 JDK를 통해 배포되는 라이브러리로 알고 있다. 그래서 JRE만 설치되었거나 classpath에 문제가 있는경우 프로그램 동작에 문제가 있을 수 있다. 필자는 Intellij를 사용하고 있는데 개발환경에서는 잘 돌아가던 코드가 운영환경에서 에러를 내는 문제를 일으키기도 했다. 이를 해소하기 위해 필자는 이 라이브러리 파일(tools.jar)을 패키지에 포함시키는 방법을 취했다.

dependencies {
    compile files("./src/libs/tools.jar")

필자는 해당 라이브러리 파일을 프로젝트 소스내에 옮겨 사용했다. 이 라이브러리의 원래 위치는 [jdk 폴더]/Contents/Home/lib 에 있다. 이는 시스템마다 다를 수 있으니 별도로 검색해서 찾기 바란다.

프로그램 코드 

먼저 VirtualMachine.list() 메서드를 통해 현재 시스템에서 실행중인 JVM List를 구한다. 

그리고 이 List중 현재 내 프로세스를 제외한 다른 JVM 중 같은 시작 클래스(main 메서드를 품고 있는 클래스)를 displayName() 으로 가지고 있는지 확인한다.

import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;


static boolean existsStarterVMInThisMachine() {

    List<VirtualMachineDescriptor> list = VirtualMachine.list();
    for(VirtualMachineDescriptor vms : list) {
        Integer vmPid = Integer.parseInt(vms.id());
        if (vmPid.equals(getCurrentProcessId())) {
            continue;
        }
        String name = vms.displayName();
        if (name.startsWith("startup.Starter")) {
            return true;
        }
    }
    return false;
}


private static Integer currentProcessId = null;
private static Integer getCurrentProcessId() {

    if (currentProcessId != null) {
        return currentProcessId;
    }

    try {
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm");
        jvm.setAccessible(true);
        sun.management.VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
        Method pidMethod = mgmt.getClass().getDeclaredMethod("getProcessId");
        pidMethod.setAccessible(true);
        currentProcessId = (Integer)pidMethod.invoke(mgmt);
        return currentProcessId;
    } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException
        | InvocationTargetException e) {
        log.error(e.getMessage());
        return -1;
    }
}

 

블로그의 정보

지금 당장 해!!!

지금당장해

활동하기