15
JAVA MEMORY / HEAP / META SPACE / PERMANENT 2017.03.12( 일 ) 일일일 Study

Java memory

  • Upload
    nim-bae

  • View
    113

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Java memory

불타는Study

Page 2: Java memory

01 Java Memory02 HEAP03 META SPACE And PERMANET

Page 3: Java memory

01 Java Memory

Java 프로그램은 JVM( 자바가상머신 ) 에서 실행이 되는데 , JVM 이 OS 에게 메모리 사용권한을 할당 받고 Java프로그램의 메모리를 관리한다 .

Page 4: Java memory

01 Java Memory

Method (Static) Area : JVM 이 읽어들인 클래스와 인터페이스 대한 런타임 상수 풀 , 멤버 변수 ( 필드 ), 클래스 변수 (Static 변수 ), 생성자와 메소드를 저장하는 공간이다 . (*.class 들을 클래스 로더로 읽어 클래스별로 런타임 상수풀 , 필드 데이터 , 메소드 데이터 , 메소드 코드 , 메소드 생성자 코드 등을 분류해서 저장 . 메소드 영역은 JVM 이 시작할 때 생성되고 , 모든 스레드가 공유하는 영역 )

Runtime Constant Pool : 메소드 영역에 포함되지만 독자적 중요성이 있다 , 클래스 파일 constant_pool 테이블에 해당하는 영역이다 , 클래스와 인터페이스 상수 , 메소드와 필드에 대한 모든 레퍼런스를 저장한다 , JVM 은 런타임 상수 풀을 통해 해당 메소드나 필드의 실제 메모리 상 주소를 찾아 참조한다* 메소드 영역 / 런타임 상수 풀의 사용기간 및 스레드 공유 범위- JVM 시작시 생성 - 프로그램 종료 시까지 - 명시적으로 null 선언 시 - GC(Garbage Collection) 대상 - 구성 방식이나 GC 방법은 JVM 벤더마다 다를 수 있다 .- 모든 스레드에서 공유한다 .

Page 5: Java memory

01 Java Memory

Heap Area : JVM 이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역이다 .- New 연산자로 생성된 객체 또는 객체 ( 인스턴스 ) 와 배열을 저장한다 .- 힙 영역에 생성된 객체와 배열은 스택 영역의 변수나 다른 객체의 필드에서 참조한다 .- 참조하는 변수나 필드가 없다면 의미 없는 객체가 되어 GC 의 대상이 된다 .(Heap Area 는 Object 와 Array 가 생성되는 영역 , 힙 영역에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조 , 참조하는 변수나 필드가 없다면 의미없는 객체가 되기 때문에 이것을 쓰레기로 취급하고 JVM GC 를 실행시켜 쓰레기 객체를 힙 영역에서 자동으로 제거 )

* 힙 영역의 사용기간 및 스레드 공유 범위- 객체가 더 이상 사용되지 않거나 명시적으로 null 선언 시- GC(Garbage Collection) 대상- 구성 방식이나 GC 방법은 JVM 벤더마다 다를 수 있다 .- 모든 스레드에서 공유한다 .

Page 6: Java memory

01 Java Memory

Stack Area : 각 스레드마다 하나씩 존재하며 , 스레드가 시작될 때 할당된다 .- 메소드를 호출할 때마다 프레임 (Frame) 을 추가 (push) 하고 메소드가 종료되면 해당 프레임을 제거 (pop) 하는 동작을 수행한다 .- 선입후출 (FILO, First In Last Out) 구조로 push 와 pop 기능 사용- 메소드 호출 시 생성되는 스레드 수행정보를 기록하는 Frame 을 저장- 메소드 정보 , 지역변수 , 매개변수 , 연산 중 발생하는 임시 데이터 저장- 기본 ( 원시 ) 타입 변수는 스택 영역에 직접 값을 가진다 .- 참조타임 변수는 힙 영역이나 메소드 영역의 객체 주소를 가진다 .

Page 7: Java memory

01 Java Memory

PC Register : - 현재 수행 중인 JVM 명령 주소를 갖는다 .- 프로그램 실행은 CPU 에서 인스트럭션 (Instruction) 을 수행 .- CPU 는 인스트럭션을 수행하는 동안 필요한 정보를 CPU 내 기억장치인 레지스터에 저장한다 .- 연산 결곽값을 메모리에 전달하기 전 저장하는 CPU 내의 기억장치( 보통 CPU 가 명령어를 처리 하는 과정에서 수행하는 동안 필요한 정보를 Register 라는 CPU 내의 기억장치에 저장해 둔다 . 이는 CPU 에 종속적 일 수 밖에 없다 . 그렇기 때문에 자바의 철학을 실현하기 위해서는 이러한 CPU 내의 Register 의 역할을 JVM 상에 논리적인 메모리 영역으로 구현 .)

Native Method Stack Area : - 자바 외 언어로 작성된 네이티브 코드를 위한 Stack 이다 .- 즉 , JNI(Java Native Interface) 를 통해 호출되는 C/C++ 등의 코드를 수행하기 위한 스택이다 .- 네이티브 메소드의 매개변수 , 지역변수 등을 바이트 코드로 저장한다 .

Page 8: Java memory

01 Java Memory

A Java method is generically a code block with a name that you can write using plain java.public void method() {

System.out.println("I'm a java method!"); }

A native method is a method that is linked to a native library. Native libraries are linked to a java program through JNI (Java Native Interface) or JNA (Java Native Access) and a native method looks like this:

public native void method();

Page 9: Java memory

01 Java Memory

Main.java:public class Main { public native int intMethod(int i); public static void main(String[] args) { System.loadLibrary("Main"); System.out.println(new Main().intMethod(2)); } }

Main.c:#include <jni.h> #include "Main.h"

JNIEXPORT jint JNICALL Java_Main_intMethod( JNIEnv *env, jobject obj, jint i) { return i * i; }

Compile and run:javac Main.java javah -jni Main gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \ -I${JAVA_HOME}/include/linux Main.c java -Djava.library.path=. Main

Output:4

Page 10: Java memory

02HEAP

Young Generation: 이 영역은 자바 객체가 생성되자마자 저장되고 , 생긴지 얼마 안되는 객체가 저장되는 공간이다 . 시간이 지나 우선순위가 낮아지면 Old 영역으로 옮겨진다 . 이 영역에서 객체가 사라질 때 Minor GC 가 발생한다 .

Old(Tenured) Generation: Young Generation 영역에서 저장되었던 객체 중에 오래된 객체가 이동되어 저장되는 영역이다 . 이 영역에서 객체가 사라질 때 Major GC(Full GC) 가 발생한다 .

Permanent Generation: 클래스 로더에 의해 로드되는 클래스 , 메소드 등에 대한 메타 정보가 저장되는 영역으로 JVM 에 의해 사용된다 . 리플렉션을 사용하여 동적으로 클래스가 로딩되는 경우에 사용된다 . 내부적으로 리플렉션 기능을 자주 사용하는 Spring Framework 를 이용할 경우 이 영역에 대한 고려가 필요하다 .

Page 11: Java memory

03META SPACE And PERMANENT

PermGen 은 무엇인가 ?Permanent Generation 은 힙 메모리 영역중에 하나로 자바 애플리케이션을 실행할때 클래스의 메타데이터를 저장하는 영역이다 .(Java 7 기준 ) 자바 개발자라면 OutOfMemoryError: PermGen Space error 이 발생했던것을 본적이 있을텐데 이는 Permanent Gen-eration 영역이 꽉 찼을때 발생하고 메모리 누수가 발생했을때 생기게 된다 . 메모리 누수의 가장 흔한 이유중에 하나로 메모리에 로딩된 클래스와 클래스 로더가 종료될때 이것들이 GC( 가비지 컬렉션 ) 이 되지 않을때 발생한다 . Permanent space : - java class, method Code 등이 저장 되는 영역 . - Class 에 대한 Meta 정보를 저장하는 공간 . (Permanent Space 는 Java Heap 의 하위 영역 ).

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 설정

Page 12: Java memory

03META SPACE And PERMANENT

OOE 발생원인 (Out Of Memory)1. 사용량 / 데이터 양이 급증 . 응용 프로그램은 일정량의 사용자 또는 특정 양의 데이터를 처리하도록 설계되었습니다 . 사용자 수가 많아 지거나 갑자기 데이터 양이 급격히 늘어나서 예상되는 임계 값을 초과하면 정상적으로 작동하기 전에 작동하는 작업이 작동을 멈추고 java.lang.OutOfMemoryError : Java 힙 공간 오류가 트리거됩니다 .

2. 메모리 누수 . 특정 유형의 프로그래밍 오류로 인해 응용 프로그램이 지속적으로 더 많은 메모리를 소비하는 형태 . 응용 프로그램의 유출 기능이 사용될 때마다 Java 힙 공간에 몇 가지 객체가 남습니다 . 시간이 지남에 따라 누출 된 오브젝트는 사용 가능한 모든 Java 힙 공간을 소비하고 이미 익숙한 java.lang.OutOfMemoryError : Java 힙 공간 오류를 트리거합니다 .

3.  Servlet 변환 , Reflection 을 사용하여 동적으로 로딩되는 Class 가 많은 경우에 발생할 수 있으며 , WAS 의 Class Reloading 기능이 자주 실행 될 경우에도 발생할 수 있음 . -> HEAP 또는 PERMANET

Page 13: Java memory

03META SPACE And PERMANENT

Permanent Generation 의 약자 인 PermGen 은 JVM 에서 클래스 및 메소드 객체를 저장하는 데 사용되는 Heap 의 메모리 영역입니다 . 응용 프로그램에 많은 클래스가로드되면 PermGen 사용률이 높아집니다 . PermGen 은 또한 'interned' 문자열을 보유하고 있습니다 . PermGen 공간의 크기는 Java 명령 행 옵션 -XX : MaxPermSize 에 의해 구성됩니다 일반적으로 256MB 는 대부분의 응용 프로그램에 필요한 PermGen 공간 이상이어야합니다 . 그러나 비정상적인 수의 클래스를로드하는 경우 "java.lang.OutOfMemoryError : PermGen space" 오류를 보는 것은 일반적이지 않습니다 . Per-mGen 공간으로 인해 OutOfMemory 오류가 발생했습니다 . Java 8 에는 PermGen 이 없습니다 . 맞습니다 . PermGen 으로 인한 OutOfMemory 오류가 없어졌습니다 . PermGen 과 Metaspace 의 주요 차이점은 PermGen 은 Java 힙 (-Xmx 옵션으로 구성된 최대 크기 ) 의 일부이지만 Metaspace 는 힙의 일부가 아닙니다 . 오히려 Metaspace 는 호스트 운영 체제에 의해서만 제한되는 기본 메모리 ( 프로세스 메모리 ) 의 일부입니다 .장점PermGen 영역이 삭제되어 heap 영역에서 사용할 수 있는 메모리가 늘어났다 .PermGen 영역을 삭제하기 위해 존재했던 여러 복잡한 코드들이 삭제 되고 PermGen 영역을 스캔 하기 위해 소모되었던 시간이 감소되어 GC 성능이 향상 되었다 .단점더 이상 PermGen 공간이 부족하지는 않지만 (PermGen 이 없으므로 ) 과도한 네이티브 메모리를 소비하여 전체 프로세스 크기가 커질 수 있습니다 . 문제는 응용 프로그램이 많은 클래스 (및 / 또는 문자열 ) 를 로드하는 경우 실제로 응용 프로그램뿐만 아니라 전체 서버를 다운시킬 수 있다는 것입니다 . 왜 ? 기본 메모리는 운영 체제에 의해서만 제한되기 때문입니다 . 즉 , 문자 그대로 서버의 모든 메모리를 차지할 수 있습니다 .

Page 14: Java memory

03META SPACE And PERMANENT

MetaspaceSize 및 MaxMetaspaceSize 가 새롭게 사용되게 되었다 . 이 두 값은 Metaspace 의 기본 값을 변경하고 최대값을 제한 할 수 있다 .

MetaspaceSize 이 설정은 JVM 이 사용하는 네이티브 메모리양을 변경하는데 사용된다 . 시스템에서 기본으로 제공되는 것보다 더 많은 메모리를 사용할 것이라고 확신할 경우 이 옵션을 사용하면 된다 . 

MaxMetaspaceSize이 설정은 metaspace 의 최대 메모리 양을 변경하는데 사용된다 . 애플리케이션을 서버에서 동작시킬때 메모리 영역을 조절하고 싶거나 메모리 누수가 발생해서 시스템 전체의 네이티브 메모리를 사용해 버리지 않도록 하기 위해서 사용하면 된다 . 만약 native 메모리가 꽉 찾는데도 애플리케이션이 메모리를 더 요구 한다면 java.lang.OutOfMemoryError: Metadata space 가 발생한다 .

참고 : https://www.slideshare.net/faizanadnan/java-8-from-perm-gen-to-metaspace

Page 15: Java memory

Thanks. Have a good day.