Runtime (1)

자바로 개발을 하다가 OOM이 발생하는 경우가 발생하면 힙메모리가 어느 지점에서 증가하는지 파악을 해야한다. 확인하는 방법은 크게 두 가지 방법이 있다. 소스레벨 수정이 가능한 경우와 소스레벨 수정이 불가능한 경우로 나뉘는데, 소스레벨 수정이 불가능하면 자바 힙 덤프를 떠서 확인을 할 수 있다. 이번 포스팅에서는 소스레벨 수정이 가능한 경우, 즉, 개발 시점에서 확인하는 방법을 얘기해보려 한다.


자바는 개발자들에게 유용한 라이브러리들은 기본적으로 제공하고있으며, 메모리 사용량 관련하여 Runtime 클래스에서 메서드를 제공하고있다.


Java 8 API 문서를 보면 아래와 같이 설명이 되어있다.


Class Runtime



  • public class Runtime
    extends Object
    Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method.

    An application cannot create its own instance of this class.

즉, 모든 자바 프로그램들은 하나의 Runtime 인스턴스를 가지고 있는데, 이 Runtime인스턴스는 프로그램이 실행되고있는 환경과 인터페이스할 수 있도록 해준다. 즉, 자바프로그램이 실행되고있는 시스템의 정보를 가져올 수 있다는 것이다. (명령어 실행도 가능하다.)


그럼 Runtime 클래스에서 어떤 메서드들을 제공하는지 한번 보자.


Modifier and Type

Method and Description
voidaddShutdownHook(Thread hook)
Registers a new virtual-machine shutdown hook.
intavailableProcessors()
Returns the number of processors available to the Java virtual machine.
Processexec(String command)
Executes the specified string command in a separate process.
Processexec(String[] cmdarray)
Executes the specified command and arguments in a separate process.
Processexec(String[] cmdarray, String[] envp)
Executes the specified command and arguments in a separate process with the specified environment.
Processexec(String[] cmdarray, String[] envp, File dir)
Executes the specified command and arguments in a separate process with the specified environment and working directory.
Processexec(String command, String[] envp)
Executes the specified string command in a separate process with the specified environment.
Processexec(String command, String[] envp, File dir)
Executes the specified string command in a separate process with the specified environment and working directory.
voidexit(int status)
Terminates the currently running Java virtual machine by initiating its shutdown sequence.
longfreeMemory()
Returns the amount of free memory in the Java Virtual Machine.
voidgc()
Runs the garbage collector.
InputStreamgetLocalizedInputStream(InputStream in)
Deprecated. 
As of JDK 1.1, the preferred way to translate a byte stream in the local encoding into a character stream in Unicode is via the InputStreamReader and BufferedReader classes.
OutputStreamgetLocalizedOutputStream(OutputStream out)
Deprecated. 
As of JDK 1.1, the preferred way to translate a Unicode character stream into a byte stream in the local encoding is via the OutputStreamWriterBufferedWriter, and PrintWriter classes.
static RuntimegetRuntime()
Returns the runtime object associated with the current Java application.
voidhalt(int status)
Forcibly terminates the currently running Java virtual machine.
voidload(String filename)
Loads the native library specified by the filename argument.
voidloadLibrary(String libname)
Loads the native library specified by the libname argument.
longmaxMemory()
Returns the maximum amount of memory that the Java virtual machine will attempt to use.
booleanremoveShutdownHook(Thread hook)
De-registers a previously-registered virtual-machine shutdown hook.
voidrunFinalization()
Runs the finalization methods of any objects pending finalization.
static voidrunFinalizersOnExit(boolean value)
Deprecated. 
This method is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock.
longtotalMemory()
Returns the total amount of memory in the Java virtual machine.
voidtraceInstructions(boolean on)
Enables/Disables tracing of instructions.
voidtraceMethodCalls(boolean on)
Enables/Disables tracing of method calls.


위 메서드들이 Runtime 클래스에서 제공하고있는 메서드들이다.

이 중에서 메모리 관련 메서드들이 몇 개 보인다.

첫 번째로 freeMemory가 있는데, 이 메서드는 힙메모리 영역에서 free메모리를 바이트단위로 계산해서 반환해준다. 그리고 maxMemory와 totalMemory가 있는데 totalMemory는 현재 애플리케이션이 사용하고있는 총 힙 메모리를 의미하며, maxMemory는 OOM(OutOfMemory)예외가 발생하는 메모리 사이즈를 반환해준다. 역시 바이트 단위이며, 애플리케이션이 이 메모리 한계를 넘어서는 순간 OOM이 발생하면서 프로그램 실행이 중단된다.


사용예를 보면 아래와 같다.


// 현재 힙 메모리 사이즈를 바이트 단위로 반환

long heapSize = Runtime.getRuntime().totalMemory(); 


// 애플리케이션에 할당된 힙메모리 사이즈. 이 사이즈를 넘어서면 OOM 발생

long heapMaxSize = Runtime.getRuntime().maxMemory();


// 현재 남아있는 free메모리. 프로그램이 실행되는 동안 증감을 반복

long heapFreeSize = Runtime.getRuntime().freeMemory();


해당 사이즈를 반환받은 뒤 KB, MB단위로 변환해주는 메서드를 만들어서 콘솔에 출력해주면 읽기가 편하다.