2012년 5월 22일 화요일
JVM Memory 영역에 대한 설명
- Method Area : 메소드와 클래스 변수를 저장하기 위한 공간, 모든 프로그램에 의해 공유.
- Heap Area : 사용자가 생성하는 Java Object들이 저장되는 공간, 동적으로 할당하여 사용되어짐.
- Stack Area : 메소드 호출시 해당 메소드의 매개변수, 지역변수, 임시변수 등을 저장하기 위한 Stack 구조의 메모리.
- Native Heap Area : Java Object가 아닌 Native Object들이 거주하는 공간. OS 차원에서 결정.
- Permanent Space : Class에 대한 Meta 정보를 저장하는 공간. (Permanent Space는 Java Heap의 하위 영역)
* Java 실행 Option
1. -X Option (모든 VM에서 동작하지 않을 수 있는 비표준 option이며, 버젼별로 언급없이 변경되어질 수 있음)
-Xms : 초기 Heap size 설정
-Xmx : 최대 Heap size 설정
-Xss : 각 Thread에 할당되는 Stack size 설정
-Xmn : New 영역을 위한 Heap size 설정
2. -XX Option (올바른 동작을 위해 특정한 시스템 요구사항들이 있으며, 시스템 설정 파라미터에 대한 접근 권한이 요구됨)
-XX:PermSize : 초기 Permanent size 설정
-XX:MaxPermSize : 최대 Permanent size 설정
※ 참고 사이트 : http://blogs.sun.com/watt/resource/jvm-options-list.html
http://www.monosun.com/doc/hotspotvmoption.html
* Heap Size 구하기
long heapSize = Runtime.getRuntime().totalMemory();
String heapSizeMB = (heapSize / (1024*1024)) + "MB";
* 영역별 OutOfMemoryError 대처 방법
1. Heap Area
Exception in thread "main": java.lang.OutOfMemoryError: Java heap space
Exception in thread main: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
원인 : Heap size의 부족으로 Java Object를 생성하지 못하여 발생
해결 : 1. -Xmx Option을 이용하여 최대 Heap size의 크기를 늘려줌
2. Application 로직이 잘못되었거나 JDK나 WAS의 Bug로 인한 Memory 누수가 있는지 확인하여 수정
3. finalize method에 의해 즉각적인 GC가 이루어지지 않으므로 로직 수정을 통해 해결
※ Object Allocation Profiling (Hprof)
java -Xrunhprof:heap=sites [Main Class]
java -Xrunhprof:heap=sites,doe=n [Main Class] (Thread Dump 생성)
2. Permanent Space
Exception in thread "main": java.lang.OutOfMemoryError: Perm Gen space'
원인 : Permanent 저장 공간이 부족하여 발생.
JSP -> Servlet 변환, Reflection을 사용하여 동적으로 로딩되는 Class가 많은 경우에 발생할 수 있으며,
WAS의 Class Reloading 기능이 자주 실행 될 경우에도 발생할 수 있음.
해결 : -XX:PermSize, -XX:MaxPermSize Option을 이용하여 크기를 늘려줌
※ Class Loading Monitoring
java 실행시 -verbose:gc을 사용하여 Class가 Loading 되는 것을 Monitoring
3. Native Heap Area
java.lang.OutOfMemoryError: request bytes for . Out of swap space?
java.lang.OutOfMemoryError: (Native method)'
java.lang.OutOfMemoryError: unable to create new native thread
원인 : Native Heap memory가 부족하여 발생
해결 : 1. Physical memory를 초과할 경우 Virtual Memory를 요청하여 필요한 메모리를 확보하게 되는데,
이 과정에서 오류가 발생할 경우 OS가 제공하는 툴을 통해 이를 모니터링 하고
이 공간 자체가 부족할 경우 크기를 늘려줌
2. -Xmx Option을 이용하여 Heap Area 공간을 줄이고 Native Heap Area 공간을 늘림
3. Thread Stack Space가 부족한 경우 Thread의 수를 줄이거나,
-Xss Option을 통해 Thread별 Stack Size를 줄여줌
(단, Thread별 Stack Size를 과도하게 줄였을 경우 Stack Overflow Error가 발생할 수 있음)
reference site:
JVM maximum size (32bit/64bit)
First of all, let's have a global look about JVM Memory.
If we are using a 32bit OS, then the jvm can't have more than 4GB of RAM
Over this 4Gig, Os have their own needs. For exemple Windows needs 2GB for its kernel usage. So it left 2GB for our JVM.
But JVM implementation needs to have a continous memory region for the heap.
Here is the explanation :
"The reason we need a contiguous memory region for the heap is that we have a bunch of side data structures that are indexed by (scaled) offsets from the start of the heap. For example, we track object reference updates with a "card mark array" that has one byte for each 512 bytes of heap. When we store a reference in the heap we have to mark the corresponding byte in the card mark array. We right shift the destination address of the store and use that to index the card mark array. Fun addressing arithmetic games you can't do in Java that you get to (have to :-) play in C++.
Usually we don't have trouble getting modest contiguous regions (up to about 1.5GB on Windohs, up to about 3.8GB on Solaris. YMMV.). On Windohs, the problem is mostly that there are some libraries that get loaded before the JVM starts up that break up the address space. Using the /3GB switch won't rebase those libraries, so they are still a problem for us.
We know how to make chunked heaps, but there would be some overhead to using them. We have more requests for faster storage management than we do for larger heaps in the 32-bit JVM. If you really want large heaps, switch to the 64-bit JVM. We still need contiguous memory, but it's much easier to get in a 64-bit address space."
So usually, JVM heap cannot be bigger than 1.2-1.6BG.
JVM memory overview
We could resume Java process heap with the following schema :
Java Heap & GC tuning
Java "Heap" is a continous memory region where all Objects data will be stored (by data, we mean instance of class, primitive and references). It's a big part of the process heap.
It can be configured using the following parameters :
-Xmx : max heap size (ex: -Xmx1024)
-Xms : min heap size. Having -Xms = 1.8GB (32bit) can be bad, because you don't let memory for anything else.
-Xmn : the size of the heap for the young generation
Young generation represents all the objects which have a short life of time. Young generation objects are in a specific location into the heap, where the garbage collector will pass often. All new objects are created into the young generation region (called "eden"). When an object survive is still "alive" after more than 2-3 gc cleaning, then it will be swap has an "old generation" : they are "survivor" .
Good size is 33%
-XX:NewRatio : the same as Wmn, but using a % (dynamic fs static -Xmn option). -XX:NewRatio=3 means that the ratio between the old and young generation is 1:3
-XX:NewSize - Size of the young generation at JVM init. Calculated automatically if you specify -XX:NewRatio
-XX:MaxNewSize - The largest size the young generation can grow to (unlimited if this value is not specified at command line)
-XX:SurvivorRatio : "old generation" called tenured generation, ratio, in %. For example, -XX:SurvivorRatio=6 sets the ratio between each survivor space and eden to be 1:6 (eden is where new objects are created)
-XX:MinHeapFreeRatio: default is 40%. JVM will allocate memory to always have as minimum 40% of free memory. When -Xmx = -Xms, it's useless.
-XX:MaxHeapFreeRatio: default is 70%. The same as Min, to avoid unecessary memory allocation.
More informationabout Sun HotSpot GC tuning here and general gc tuning here
At this point, we get a problem. In a multithread application, object can be created at the same time. Thread could try to write data into the same heap location at the same time.
To avoid this problem, we allow each thread to have a private piece into the eden space.
jdk 1.5> uses dynamic sizing algorithm, specific for each thread. (otherwise, parameter such as -XX:UseTLAB or -XX:TLABSize can be used to tune this parameter)
And EveryThing Else...
Every thing else is...
Permanent Space : It's the third part of the memory. Here are stored classes, methods etc.
-XX:PermSize: initial value
-XX:MaxPermSize: max value
Code generation : Converted byte code into native code. Shouldn't cause troubles.
Socket Buffer (contains the 2 buffers for each sockets: receive/send)
Thread Stacks: Each thread has its own stack. It makes possible to get your methods thread-safe.
-Xss: change the space of a thread stack. 2048 could be a write value. It can cause a java.lang.stackOverFlow Error
If you get a "java.lang.OutOfMemoryError : unable to create new native Thread, you can decrease -Xss or decrease the java heap using -Xmx/-Xms (to increase the thread stack space)
Direct memory space (ability to let Java developers map memory outside the Java Object Heap. Can be adjusted using -XX:MaxDirectMemory=
JNI Code, if you use it
Garbage Collection (the GC has its own thread/informations)
A nice gotcha...
Major collection don't run until tenured is full.
This mean that using -Xmx1024, current heap could be 750MB with 500MB of "dead" object. If the JVM is idle, it could stay like that during a very long time => wasting 500MB or RAM for an idle JVM !
More informations about GC memory & monitoring here
You should also read this awesome slideshare from Filip Hanik, Covalent (gotcha, etc... most of this informations come from this slides)
프로그램은 실행되면서 저장할 데이터가 있으면 메모리의 일정 공간을 할당받아서 사용하게 된다. 그런데 이 데이터가 더 이상 사용할 필요가 없는것이면, 사용항 메모리를 반납해야주어야한다.
자바는 친절히도 메모리 회수를 자동적으로 해준다. 즉, JVM(Java Virtual Machine)의 Garbage Collector란 놈이 사용하지 않는 메모리를 알아서 회수해주는것이다. 이 회수에 대한 행위를 GC(Garbage Collection)이라한다.
JVM의 메모리 영역은 크게 Heap Area과 Non-Heap Area으로 나눌수 있다.
1. Heap Area
힙 영역(Heap Area)은 동적으로 할당하여 사용할 수 있는 메모리 영역으로서, 주로 실행중에 생성되는 객체들이 저장된다. 이 힙 영역(Heap Area)이 GC(Garbage Collection)의 대상이 되는 메모리 영역이다. 즉, Garbage Collector에 의해서 이 힙영역중에 사용하지 않는 메모리가 회수되는것이다.
힙 영역(Heap Area)을 세분화하면 일반적으로 세 영역으로 나눌 수 있다.
1.1. Young(New) Object Space : 새로 생성한 객체를 저장하능 영역이다. 이 부분은 다시 세 부분으로 나누어진다.
새로 생성한 모든 객체들이 가는 Eden 영역과 Old Object Space가기전에 거치는 SS1(Survivor Space 1), SS2(Survivor Space 2) 영역(From Space, To Space 라고 부르기도 한다.)이 있다. 이 Young 영역의 GC를 Minor GC(Scavenge GC)라 부른다. 객체가 탄생(?)하면 Eden 영역에 놀다가, Minor GC가 발생하면 살아있는것들은 S1으로 보내고, 나머지는 제거(?)해버린다. 그리고 다음번 Minor GC가 발생하면 S1 영역의 객체중 살아있는것은 SS2로 복사(실제적으로 레퍼런스 주소만 변경)한후 Eden, S1 영역을 초기화(Clear) 해버린다. 이렇게 Minor GC를 실행하다가 오래된 객체를 Old Object Space로 옮기는것이다.
1.2. Old Object Space: Young(New) 영역에서 살아남은(?) 객체가 이동되어 저장되는 영역이다.
이 Old 영영의 GC를 Full GC라 부른다. 일반적으로 사용되는 Full GC 알고리즘은 사용하는 객체들의 레퍼런스(reference)를 찾아 연결되지 않는 객체를 표시(Mark)한 다음, 작업이 끝난후 표시한 객체를 모두 삭제를 하는 방법이다. Full GC는 속도가 매우 느리고, 실행되는 동안에 순간적으로 프로그램이 멈춰버리기 때문에 어플리케이션(Application)의 성능에 큰 영향을 준다. 그래서 여러가지 GC 알고리즘을 지원한다.
1.3. Permanet Space : 클래스와 메소드등의 메타정보를 저장하는 영역이다. (논리적인 Heap 영역으로서, -Xms, -Xmx에서 말하는 Heap 영역에서는 제외된다.)
2. Non-Heap Area
Non-Heap 영역은 Heap 이외의 영역을 말한다.(당연한 말을 ^^;)
2.1. Method Area : 메소드와 클래스 변수를 저장하기 위한 영역이다.
2.2. Stack Area : 메소드 호출 시 메소드의 매개변수, 지역변수, 임시변수등을 저장하기 위한 스택 구조의 영역이다.
2.3. 기타 : JVM이 현재 수행할 명령어의 주소를 저장하는 PC 레지스터, native 메소드의 매개변수, 지역변수 등을 저장 native 메소드 스택등이 있다.
3. JVM 실행 Option
참고 : http://blogs.sun.com/watt/resource/jvm-options-list.html
- 이 옵션들을 JVM에 따라 형식이 조금씩 다를 수 있고, 지원하지 않을 수도 있다.
3.1. -X Option
-Xms : 초기 Heap size (Young + Old)
-Xmx : 최대 Heap size (Young + Old)
-Xss : 각 Thread별 Stack size
-Xmn : Young(New) 영역 크기
3.2. -XX Option
-XX:PermSize : 초기 Permanent size
-XX:MaxPermSize : 최대 Permanent size
-XX:SurvivorRatio=<n> : Eden 영역의 크기를 SS1 또는 SS2의 크기로 나눈값
-XX:NewRatio : Old/New Size 값이다. (전체 Heasp Size가 768m일때 NewRatio=2이면, New=256m, Old=512m으로 설정된다.)
3.3. 메모리 산출 공식
YOUNG = Xmn = Eden + SS1 + SS2
Eden = YOUNG - ((Xmn/(SurvivorRatio + 2)) * 2)
SS1 = (YOUNG - Eden)/2
SS2 = (YOUNG - Eden)/2
OLD = Xmx - Xmn
3.4. -verbosegc
자바 실행시 JVM 옵션에 -verbosegc 를 주면 GC 로그를 볼 수 있다.
* 실행 결과
[GC 5971K->5481K(7748K), 0.0011015 secs]
[GC 5993K->5498K(7748K), 0.0010708 secs]
[GC 6008K->5523K(7748K), 0.0011719 secs]
[GC 6027K->5588K(7748K), 0.0010359 secs]
[GC 6089K->5695K(7748K), 0.0012088 secs]
[Full GC 5737K->5641K(7748K), 0.0630893 secs]
[GC 6345K->5945K(10172K), 0.0017444 secs]
[GC 6649K->5944K(10172K), 0.0010166 secs]
[GC 6648K->6000K(10172K), 0.0011124 secs]
[GC 6704K->6048K(10172K), 0.0015901 secs]
[GC 6752K->6059K(10172K), 0.0006417 secs]
[GC 6763K->6116K(10172K), 0.0006613 secs]
[GC 6763K->6116K(10172K), 0.0006613 secs]
Minor GC는 "GC"로, Full GC는 "Full GC"로 나타난다.
6763K은 GC하기 전의 Heap Size이고, 6116K은 GC후의 Heap 사이즈를 나타낸다.
(10172K)은 총 Heasp Size이고, 0.0006613 secs은 GC 소요 시간이다.
4. java.lang.OutOfMemoryError
- 잊혀질만하면 나타나는 우리의 친구 OutOfMemory. 프로그램에 메모리 누수등의 문제가 없다면, JVM 옵션으로 메모리를 늘려주면 된다. 이 OutOfMemory도 메모리 종료(?)별로 발생하는데, 가장 빈번하게 발생하는 놈은 heap과 PermGen이라는 놈이다.
4.1. java.lang.OutOfMemoryError: Java heap space
- 가장 유명한 놈으로서, Heap 크기가 부족해서 나는것이다.
- 해결책 : -Xmx 옵션을 이용해서 최대 Heap Size를 늘려준다.
4.2.java.lang.OutOfMemoryError: PermGen space
- 요즘 뜨는 놈인데, 동적 클래스를 많이 사용할 경우 발생한다. JSP->Server 변환이나, spring 같은 동적 클래스를 많이 사용하는 프레임워크를 사용할때 종종 발생한다.
- 해결책 : -XX:MaxPermSize 옵션을 이용해서 Perm Size를 늘려준다.
4.3. 기타
- 이 외에도 Native Heap Space가 부족하거나, Thread Stack Space가 부족할 경우 발생하기도 하는데, 보통은 거의 볼 수 없으므로 생략.(Native Heap Space가 부족할 경우는 Heap 사이즈를 줄여주면 되고, Thread Stack Space가 부족할경우는 Thread 수를 줄이던지 Stack Size를 줄이면 된다.)
- 32bit JVM일 경우 일반적으로 사용 가능한 메모리 크기는 4G이다.(OS에 따라 다르기도 하다) 232=4*230=4G이니까.
- 단순히 메모리 부족(?) 때문에 생기는 문제라면, 위에처럼 메모리를 늘려주면 된다. 하지만 프로그램의 버그때문에 메모리 누수현상이 발생하여 에러가 발생할경우는 참 난감할것이다. 이럴 경우는 HProf나 Heap Dump를 이용해서 잘못된 부분을 찾는 수밖에 없다. 요즘은 JMX(Java Management eXtensions)을 이용해 실시간 모니터링도 되니 정말 편한 세상이다.
2012년 5월 11일 금요일
introduction of the Mockup tool "Balsamiq"
It is very fantastic tool.
In the design phase, it makes our to draw a screen composition.
Please see the following url.
http://www.balsamiq.com/
피드 구독하기:
글 (Atom)