Java에서 가비지 수집이 자동화된다는 것을 알고 있습니다. 그러나 System.gc()코드를 호출 하면 JVM이 해당 시점에서 가비지 수집을 수행할지 여부를 결정할 수 있음을 이해 했습니다. 이것이 정확히 어떻게 작동합니까? JVM은 정확히 어떤 기준 / 매개 변수에서 GC를 수행할지 여부를 결정 System.gc()합니까?
이것을 코드에 넣는 것이 좋은 경우에 대한 예가 있습니까?
Java에서 가비지 수집이 자동화된다는 것을 알고 있습니다. 그러나 System.gc()코드를 호출 하면 JVM이 해당 시점에서 가비지 수집을 수행할지 여부를 결정할 수 있음을 이해 했습니다. 이것이 정확히 어떻게 작동합니까? JVM은 정확히 어떤 기준 / 매개 변수에서 GC를 수행할지 여부를 결정 System.gc()합니까?
이것을 코드에 넣는 것이 좋은 경우에 대한 예가 있습니까?
답변:
실제로는 일반적으로 가비지 콜렉션을 수행하기로 결정합니다. 대답은 실행중인 JVM, 어떤 모드에 있는지, 사용중인 가비지 수집 알고리즘과 같은 많은 요인에 따라 다릅니다.
나는 당신의 코드에서 그것에 의존하지 않을 것입니다. JVM이 OutOfMemoryError를 발생시키려는 경우 System.gc () 호출은이를 중지하지 않습니다. 가비지 컬렉터가 극도로 진행되기 전에 가능한 한 많이 해제하려고하기 때문입니다. 내가 실제로 사용하는 것을 본 유일한 시간은 사용자가 클릭 할 수있는 버튼에 연결된 IDE에 있지만 그다지 유용하지는 않습니다.
System.gc()비디오 게임의 로딩 화면에서 사용 합니다. 그 시점에서 나는 전화가 가능한 모든 것을 제거했는지, 아니면 아무것도하지 않았는지 상관하지 않을 것이다. 그러나 나는 게임 플레이가 아닌 로딩 화면에서 "사용하지 않는 개체를 재활용하는 데 노력을 기울이는" 것을 선호 합니다.
System.gc ()를 호출하는 것이 합리적이라고 생각할 수있는 유일한 예는 가능한 메모리 누수를 검색하기 위해 애플리케이션을 프로파일 링 할 때입니다. 프로파일 러는 메모리 스냅 샷을 찍기 직전에이 메서드를 호출한다고 생각합니다.
Java 언어 사양은를 호출 할 때 JVM이 GC를 시작한다고 보장하지 않습니다 System.gc(). 이것이 "그 시점에서 GC를 수행하기로 결정할 수도 있고 결정하지 않을 수도 있습니다"의 이유입니다.
이제 Oracle JVM의 중추 인 OpenJDK 소스 코드 를 살펴보면에 대한 호출 System.gc()이 GC주기를 시작 한다는 것을 알 수 있습니다. J9와 같은 다른 JVM을 사용하는 경우 해당 문서를 확인하여 답을 찾아야합니다. 예를 들어 Azul의 JVM에는 지속적으로 실행되는 가비지 수집기가 있으므로에 대한 호출 System.gc()은 아무 작업도 수행하지 않습니다.
다른 답변은 JConsole 또는 VisualVM에서 GC 시작을 언급합니다. 기본적으로 이러한 도구는 System.gc().
일반적으로 코드에서 가비지 수집주기를 시작하고 싶지 않습니다. 애플리케이션의 의미 체계를 망칠 수 있기 때문입니다. 애플리케이션은 비즈니스 작업을 수행하고 JVM은 메모리 관리를 처리합니다. 이러한 문제를 분리해야합니다 (애플리케이션이 메모리 관리를 수행하도록하지 말고 비즈니스에 집중).
그러나에 대한 호출을 System.gc()이해할 수있는 경우는 거의 없습니다 . 예를 들어 마이크로 벤치 마크를 고려하십시오. 아무도 마이크로 벤치 마크 중간에 GC주기가 발생하기를 원하지 않습니다. 따라서 각 측정 사이에 GC주기를 트리거하여 모든 측정이 빈 힙으로 시작되도록 할 수 있습니다.
Java에서 GC를 제어 할 수 없습니다. VM이 결정합니다. 나는 사례를 통해 실행 적이 System.gc()있다 필요합니다 . 때문에 System.gc()호출이 단순히 VM은 가비지 수집을 할 것을 제안하고 또한 전체 가비지 컬렉션 (다중 세대 힙에 이전 및 새 세대)를 수행 한 후 실제로 발생할 수 있습니다 더 많은 CPU 사이클이 필요 이상으로 소비 될 수 있습니다.
어떤 경우에는 애플리케이션이 무거운 작업이 발생하기 전에 다음 몇 분 동안 유휴 상태가 될 것임을 알 수 있으므로 VM이 지금 전체 수집을 수행하도록 제안하는 것이 합리적 일 수 있습니다. 예를 들어, 응용 프로그램을 시작하는 동안 많은 임시 개체를 초기화 한 직후 (즉, TON의 정보를 캐시했으며 1 분 정도는 많은 활동을하지 않을 것임을 알고 있습니다). Eclipse 시작과 같은 IDE를 생각해보십시오. 초기화에 많은 작업을 수행하므로 아마도 초기화 직후에 전체 gc를 수행하는 것이 좋습니다.
전화 할 경우 매우 조심해야합니다 System.gc(). 이를 호출하면 애플리케이션에 불필요한 성능 문제가 추가 될 수 있으며 실제로 수집을 수행한다고 보장 할 수 없습니다. 실제로 System.gc()java 인수를 통해 명시 적을 비활성화 할 수 있습니다 -XX:+DisableExplicitGC.
가비지 컬렉션에 대한 자세한 내용은 Java HotSpot Garbage Collection 에서 제공하는 문서를 읽어 보는 것이 좋습니다 .
직접 메모리 버퍼를 사용하는 경우 직접 메모리가 부족하더라도 JVM이 GC를 실행하지 않습니다.
전화를 걸고 ByteBuffer.allocateDirect()OutOfMemoryError가 발생하면 GC를 수동으로 트리거 한 후이 호출이 괜찮다는 것을 알 수 있습니다.
Cleaners직접 메모리가 사용하는 지름길이 있습니다. 즉, 너무 느릴 수 있으므로 종료 자 스레드에 의해 해제되지 않습니다. 그렇더라도 직접 메모리 영역을 특히 빠르게 생성하는 경우 OOME을 얻을 수 있습니다. 해결책은 그렇게하지 않고 가능한 한 직접 메모리 영역을 재사용하는 것입니다.
대부분의 JVM은 GC를 시작합니다 (-XX : DiableExplicitGC 및 -XX : + ExplicitGCInvokesConcurrent 스위치에 따라 다름). 그러나 나중에 더 나은 구현을 허용하기 위해 사양이 잘 정의되어 있지 않습니다.
사양에 설명이 필요합니다. 버그 # 6668279 : (spec) System.gc ()는 사용을 권장하지 않으며 동작을 보장하지 않음을 나타내야합니다.
내부적으로 gc 메소드는 RMI 및 NIO에서 사용되며 동기 실행이 필요합니다. 이는 현재 논의 중입니다.
버그 # 5025281 : System.gc ()가 동시 (stop-the-world 아님) 전체 수집을 트리거하도록 허용
Garbage CollectionJava데스크톱 / 노트북 / 서버에서 자바로 코딩 된 소프트웨어를 실행하는 경우 에서 좋습니다 . System.gc()또는 Runtime.getRuntime().gc()으로 전화 할 수 있습니다 Java.
이러한 호출 중 어떤 것도 아무 작업도 수행하지 않는다는 점에 유의하십시오. 이는 jvm이 가비지 콜렉터를 실행하기위한 제안 일뿐입니다. GC를 실행하는지 여부는 JVM이 결정합니다. 그래서 짧은 대답 : 우리는 그것이 언제 실행되는지 모릅니다. 더 긴 대답 : JVM은 시간이 있으면 gc를 실행합니다.
Android에도 동일하게 적용됩니다. 그러나 이로 인해 시스템 속도가 느려질 수 있습니다.
일반적으로 VM은 OutOfMemoryException을 발생시키기 전에 자동으로 가비지 수집을 수행하므로 명시 적 호출을 추가해도 성능 저하가 이전 시점으로 이동한다는 점을 제외하고는 도움이되지 않습니다.
그러나 관련성이있을 수있는 경우를 만난 것 같습니다. 아직 효과가 있는지 테스트하지 않았기 때문에 확실하지 않습니다.
파일을 메모리 매핑 할 때 충분한 메모리 블록을 사용할 수 없을 때 map () 호출이 IOException을 던진다 고 생각합니다. map () 파일 바로 앞에 가비지 컬렉션이 도움이 될 수 있다고 생각합니다. 어떻게 생각해?
다양한 가비지 컬렉션 설정을 테스트하는 데 시간을 할애하는 데에는 많은 말이 있지만 위에서 언급했듯이 일반적으로 그렇게하는 것은 유용하지 않습니다.
저는 현재 메모리가 제한된 환경과 상대적으로 많은 양의 데이터를 포함하는 프로젝트를 진행하고 있습니다. 내 환경을 한계까지 밀어 붙이는 큰 데이터가 몇 개 있으며 메모리 사용량을 줄일 수 있었음에도 불구하고 이론적으로는 잘 작동해야하지만 여전히 힙 공간 오류가 발생합니다. 자세한 GC 옵션은 가비지 수집을 시도했지만 아무 소용이 없음을 보여주었습니다. 디버거에서 System.gc ()를 수행 할 수 있고 "많은"메모리를 사용할 수있을 것입니다. 여분이 많지는 않지만 충분합니다.
결과적으로 내 응용 프로그램이 System.gc ()를 호출하는 유일한 시간은 데이터 처리에 필요한 큰 버퍼가 할당되는 코드 세그먼트에 들어 가려고 할 때이며 사용 가능한 메모리에 대한 테스트는 내가 그렇지 않다는 것을 나타냅니다. 그것을 보장합니다. 특히, 처리중인 데이터가 최소 100-200MB 인 경우를 제외하고는 정적 데이터가 최소 300MB를 차지하는 1GB 환경을 살펴보고 있습니다. 소스. 이는 모두 자동 데이터 변환 프로세스의 일부이므로 데이터는 모두 장기적으로 비교적 짧은 기간 동안 존재합니다.
안타깝게도 가비지 수집기를 조정하는 다양한 옵션에 대한 정보를 사용할 수 있지만 대부분 실험적인 프로세스로 보이며 이러한 특정 상황을 처리하는 방법을 이해하는 데 필요한 하위 수준의 세부 사항을 쉽게 얻을 수 없습니다.
내가 System.gc ()를 사용하고 있음에도 불구하고, 나는 여전히 명령 줄 매개 변수를 사용하여 조정을 계속했고, 극복 할 수 없었음에도 불구하고 내 애플리케이션의 전체 처리 시간을 상대적으로 상당히 향상시킬 수 있었다. 더 큰 데이터 블록으로 작업함으로써 발생하는 걸림돌. 즉, System.gc ()는 도구입니다 .... 매우 신뢰할 수없는 도구입니다. 사용 방법에주의를 기울이지 않으면 자주 작동하지 않는 것이 좋습니다.
System.gc()호출 여부를 알고 싶다면 새로운 Java 7 업데이트 4를 통해 JVM이 가비지 수집을 수행 할 때 알림을받을 수 있습니다.
릴리스 노트에서 찾을 수 없기 때문에 GarbageCollectorMXBean 클래스가 Java 7 업데이트 4에 도입 되었는지 100 % 확신 하지 못하지만 javaperformancetuning .com 사이트 에서 정보를 찾았습니다.
명시적인 GC를 실행하는 것이 좋을 때 구체적인 예를 생각할 수 없습니다.
일반적으로 명시 적 GC를 실행하면 실제로는 좋은 것보다 더 많은 해를 끼칠 수 있습니다. 명시 적 GC는 모든 객체를 통과 할 때 훨씬 더 오래 걸리는 전체 컬렉션을 트리거하기 때문입니다. 이 명시 적 gc가 반복적으로 호출되면 전체 GC를 실행하는 데 많은 시간이 소요되므로 애플리케이션 속도가 느려질 수 있습니다.
또는 힙 분석기로 힙을 살펴보고 라이브러리 구성 요소가 명시 적 GC를 호출하는 것으로 의심되는 경우 JVM 매개 변수에 gc = -XX : + DisableExplicitGC를 추가하여 해제 할 수 있습니다.