JVM은 힙과 비힙이라는 두 가지 유형의 메모리를 관리합니다. 힙은 위에서 언급한 것처럼 개발자가 사용하기 위한 것이며, JVM이 시작될 때 생성됩니다. 비힙은 JVM 자체가 클래스 정보를 저장하도록 예약되어 있습니다. GC는 런타임 중에 공간을 해제하지 않습니다.
1. 메모리 오버플로 유형
1. java.lang.OutOfMemoryError: PermGen 공간
JVM은 힙과 비힙이라는 두 가지 유형의 메모리를 관리합니다. 힙은 위에서 언급한 것처럼 개발자가 사용하기 위한 것이며, JVM이 시작될 때 생성됩니다. 비힙은 JVM 자체가 클래스 정보를 저장하도록 예약되어 있습니다. GC는 런타임 중에 공간을 해제하지 않습니다. 웹 앱이 많은 수의 타사 jar를 사용하거나 애플리케이션에 클래스 파일이 너무 많고 MaxPermSize 설정이 작은 경우 제한을 초과하면 메모리가 너무 많이 차지하여 오버플로가 발생하거나 Tomcat이 핫 배포 중에 전면을 정리하지 않습니다. 로드된 환경은 컨텍스트를 새로 배포된 환경으로만 변경하며 스택되지 않는 콘텐츠가 점점 더 많아집니다.
PermGen 공간의 전체 이름은 Permanent Generation 공간으로, 메모리의 영구 저장 영역을 의미합니다. 이 메모리는 주로 JVM에서 클래스를 저장하는 데 사용되며 클래스는 PermGen 공간에 배치됩니다. Loader에 의해 로드되며 클래스 인스턴스를 저장합니다.(인스턴스) Heap 영역이 다르므로 GC(Garbage Collection)는 기본 프로그램 실행 중에 PermGen 공간을 정리하지 않으므로 애플리케이션에 CLASS, PermGen이 많은 경우 나타날 가능성이 높습니다. 공간 오류, 이 오류는 웹 서버가 JSP를 사전 컴파일할 때 흔히 발생합니다. WEB APP에서 다수의 타사 jar를 사용하고 해당 크기가 jvm(4M)의 기본 크기를 초과하는 경우 이 오류 메시지가 생성됩니다.
최고의 구성 예: (직접 확인한 후 이 구성을 사용한 이후 Tomcat은 다시는 죽지 않았습니다.)
JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m을 설정합니다.
Linux에서는 tomcathome/conf/catalina.sh에 빨간색으로 표시된 코드 줄을 추가합니다. Tomcat jvm의 메모리를 늘려 메모리 오버플로가 발생할 가능성을 줄일 수 있습니다!
# ----- 요청된 명령을 실행합니다 --------------------------- -
JAVA_OPTS="-서버 -Xms512m -Xmx2048m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=256m"
# Bugzilla 37848: TTY가 있는 경우에만 이것을 출력합니다.
2. java.lang.OutOfMemoryError: Java힙 공간
첫 번째 상황은 보완적인 상황인데, 이 상황에서 가장 큰 문제가 발생한다. 기본 공간(즉, -Xms)은 물리적 메모리의 1/64이고, 최대 공간(-Xmx)은 물리적 메모리의 1/4입니다. 남은 메모리가 40% 미만인 경우 JVM은 Xmx에 설정된 값으로 힙을 늘립니다. 남은 메모리가 70%를 초과하는 경우 JVM은 Xms에 설정된 값으로 힙을 줄입니다. 따라서 각 GC 후에 가상 머신 힙의 크기가 조정되지 않도록 서버의 Xmx 및 Xms 설정은 일반적으로 동일하게 설정되어야 합니다. 물리적 메모리가 무한하다고 가정하면 최대 JVM 메모리는 운영 체제에 따라 다릅니다. 일반적으로 32비트 시스템은 1.5g에서 3g 사이이지만 64비트 시스템에는 제한이 없습니다.
참고: Xms가 Xmx 값을 초과하거나 최대 힙 값과 최대 비힙 값의 합이 실제 메모리 또는 운영 체제의 최대 제한을 초과하는 경우 서버가 시작되지 않습니다.
가비지 컬렉션 GC의 역할
JVM이 GC를 호출하는 빈도는 여전히 매우 높으며 가비지 수집은 두 가지 주요 상황에서 수행됩니다.
애플리케이션 스레드가 유휴 상태일 때, 다른 하나는 Java 메모리 힙이 부족할 때 GC가 계속 호출됩니다. 지속적인 재활용으로 메모리 힙 부족 문제를 해결할 수 없으면 메모리 부족 오류가 보고됩니다. 이 예외는 시스템 운영 환경에 따라 달라지므로 언제 발생할지 예측할 수 없습니다.
GC 메커니즘에 따르면 프로그램을 실행하면 시스템 운영 환경이 변경되어 GC가 발생할 가능성이 높아집니다.
이러한 문제를 피하기 위해서는 프로그램 설계와 작성 시 가비지 객체의 메모리 점유와 GC의 오버헤드를 피해야 합니다. System.GC()를 명시적으로 호출하면 JVM이 메모리의 가비지 개체를 재활용해야 하지만 즉시 재활용할 필요는 없다는 점만 제안할 수 있습니다.
하나는 메모리 자원 부족 문제를 해결할 수 없고, GC 소모도 늘어나게 된다는 점이다.
2. JVM 메모리 영역의 구성 <BR>자바의 힙과 스택에 대해 간단히 이야기해보자.
Java는 메모리를 두 가지 유형으로 나눕니다. 하나는 스택 메모리이고 다른 하나는 힙 메모리입니다.
1. 함수에 정의된 기본형 변수와 객체 참조 변수는 함수의 스택 메모리에 할당됩니다.
2. 힙 메모리는 new로 생성된 객체와 배열을 저장하는 데 사용됩니다. 함수(코드 블록)에 변수가 정의되면 Java는 변수의 범위를 초과하면 스택에 해당 변수에 대한 메모리 공간을 할당합니다. 변수에 할당된 메모리 공간을 제거합니다. 힙에 할당된 메모리는 Java 가상 머신의 자동 가비지 수집기에 의해 관리됩니다. 힙의 장점은 메모리 크기를 동적으로 할당할 수 있다는 것입니다. 메모리에 있으므로 런타임에 동적으로 할당되므로 미리 컴파일러에 알릴 필요가 없습니다. 단점은 메모리가 런타임에 동적으로 할당되어야 하고 액세스 속도가 느리다는 것입니다.
스택의 장점은 힙보다 액세스 속도가 빠르다는 것입니다. 단점은 스택에 저장된 데이터의 크기와 수명이 결정적이어야 하고 유연성이 없어야 한다는 것입니다.
Java 힙은 New, Old 및 Permanent의 세 가지 영역으로 나뉩니다.
GC에는 두 개의 스레드가 있습니다.
새로 생성된 객체는 New 영역에 할당되며, 해당 영역이 채워지면 GC 보조 스레드에 의해 Old 영역으로 이동되며, Old 영역도 채워지면 GC 메인 스레드가 트리거되어 해당 영역의 모든 객체를 순회하게 됩니다. 힙 메모리. Old 영역의 크기는 Xmx에서 -Xmn을 뺀 것과 같습니다.
Java 스택 스토리지 스택 조정: 매개변수는 +UseDefaultStackSize -Xss256K입니다. 이는 각 스레드가 256k 스택 공간을 적용할 수 있음을 의미합니다.
3. JVM에서 가상 메모리를 설정하는 방법 <BR>Tip: JVM에서 98%의 시간이 GC에 사용되고 사용 가능한 힙 크기가 2% 미만인 경우 이 예외 메시지가 발생합니다.
팁: 최대 힙 크기는 사용 가능한 물리적 메모리의 80%를 초과할 수 없습니다. 일반적으로 -Xms 및 -Xmx 옵션은 동일한 값으로 설정되어야 하며 -Xmn은 -Xmx 값의 1/4이어야 합니다.
팁: JVM이 할당하는 초기 메모리는 -Xms로 지정되며 기본값은 물리적 메모리의 1/64입니다. JVM이 할당하는 최대 메모리는 -Xmx로 지정되며 기본값은 물리적 메모리의 1/4입니다. 메모리.
기본적으로 사용 가능한 힙 메모리가 40% 미만인 경우 JVM은 최대 제한인 -Xmx까지 힙을 늘립니다. 사용 가능한 힙 메모리가 70%를 초과하는 경우 JVM은 최소 한도인 -Xmx까지 힙을 줄입니다. -Xms. 따라서 서버는 일반적으로 각 GC 후에 힙 크기를 조정하지 않도록 -Xms 및 -Xmx를 동일하게 설정합니다.
Tip: 물리적 메모리가 무한하다고 가정할 때 JVM 메모리의 최대값은 운영체제와 큰 관계를 갖는다.
간단히 말해서, 32비트 프로세서의 제어 가능한 메모리 공간은 4GB이지만 특정 운영 체제에서는 제한이 있습니다.
이 제한은 일반적으로 2GB~3GB(일반적으로 Windows 시스템에서는 1.5G~2G, Linux 시스템에서는 2G~3G)이며 64비트 이상의 프로세서에는 제한이 없습니다.
참고: Xms가 Xmx 값을 초과하거나 최대 힙 값과 최대 비힙 값의 합이 실제 메모리 또는 운영 체제의 최대 제한을 초과하는 경우 서버가 시작되지 않습니다.
팁: NewSize와 MaxNewSize를 동일하게 설정하고 "new"의 크기는 "old"의 절반보다 커서는 안 됩니다. 그 이유는 이전 영역이 충분히 크지 않으면 "main" GC가 자주 트리거되기 때문입니다. , 이는 성능을 크게 저하시킵니다.
JVM은 -XX:PermSize를 사용하여 힙이 아닌 메모리의 초기 값을 설정합니다. 기본값은 실제 메모리의 1/64입니다.
힙이 아닌 최대 메모리 크기는 XX:MaxPermSize로 설정됩니다. 기본값은 실제 메모리의 1/4입니다.
해결 방법: 힙 크기를 수동으로 설정
TOMCAT_HOME/bin/catalina.bat 수정
"echo "Using CATALINA_BASE: $CATALINA_BASE"" 위에 다음 줄을 추가합니다.
JAVA_OPTS="-서버 -Xms800m -Xmx800m -XX:MaxNewSize=256m"
4. 성능 검사 도구를 사용하여 메모리 누수를 찾습니다.
JProfiler 도구는 주로 시스템 성능을 확인하고 추적하는 데 사용됩니다(Java 개발로 제한됨). JProfiler는 시스템의 메모리 사용량, 가비지 수집, 스레드 실행 상태 및 기타 수단을 언제든지 지속적으로 모니터링하여 JVM 작업 및 성능을 모니터링할 수 있습니다.
1. 애플리케이션 서버의 메모리가 장기간 부당하게 점유되고 있다. 메모리가 높은 수준에서 점유되어 낮은 수준으로 복구하기 어려운 경우가 많다.