n 프로세스마다 n 분마다 스크립트를 실행하는 Java 7 프로젝트가 있습니다. 다음은 스크립트를 실행하는 코드 예제입니다. 그루비 몇 가지 이유로 Groovy 업데이트로 인해 PermGen에 죽은 GroovyClassLoaders가 발생했습니다
ScheduledFuture scheduledFuture = scheduledService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try (GroovyClassLoader cl = new GroovyClassLoader()) {
// Load up reusable script modules in the class loader
Class scriptClass = cl.parseClass(scriptSource);
Foo script = optimizationClass.newInstance();
// Tell Groovy that we don't need class meta info
GroovySystem.getMetaClassRegistry().removeMetaClass(scriptClass);
script.run();
cl.clearCache();
} catch (IOException e) {
LOGGER.error("Failed to cleanup Groovy class loader, this will cause a memory leak", e);
}
}
}, 0, scheduledRun, TimeUnit.SECONDS);
scheduledFuture.get();
은 2.3.8 또는 그루비 2.2.0가, 파마 세대가 죽은 그루비 클래스 로더 가득지고 계속 그루비로 업그레이드 파마 창에는 메모리 누수가 없다 2.1.7.
0x000000071ada2cd0 33 488160 0x000000071b2493c8 dead groovy/lang/[email protected] 0x00000007265883b8 33 488160 0x0000000725837270 dead groovy/lang/[email protected] 0x00000007157b5da0 26 370736 0x000000072326f468 live org/codehaus/groovy/runtime/callsite/[email protected] 0x000000071ada1fb0 32 423944 0x000000071af03a98 dead groovy/lang/[email protected] 0x0000000719d605b0 32 456520 0x000000071af04798 dead groovy/lang/[email protected] 0x0000000725b82500 0 0 0x000000072326f468 dead groovy/lang/[email protected] 0x00000007263eef80 34 532448 0x0000000726d5c678 dead groovy/lang/[email protected] 0x000000072687b3c8 33 485288 0x0000000726c36340 dead groovy/lang/[email protected] 0x0000000725d56db0 33 485288 0x000000072607bcc0 dead groovy/lang/[email protected]
Full GC가 발생할 때까지 기다렸지 만 Groovy 2.2 이후의 모든 버전이 Perm Gen을 채우고있는 것으로 보입니다. 내가 업데이트 된 버전까지 있던 버전 사이의 릴리스 정보를 확인한 결과,이 변경 사항을 알리는 변경 사항을 발견하지 못했습니다.
여기에 비슷한 문제가 있는지 확인하고 몇 가지 제안을 시도했지만 운이 없었습니다. 원인에 대한 아이디어가 있습니까?
업데이트 :
GroovyClassLoader의 GrepCode에서 Diff를 2.1.7에서 2.2.0으로 변경했는데 변경 사항이 없습니다. 또한 응용 프로그램이 실행 중일 때 힙 덤프 파일을 가져 왔으며 강력한 참조를 위해 GC 루트에 대한 경로가 없었습니다. 내가 스크립트를 컴파일하지만 실행하지 않는 경우 내가 파마 창에서 0 그루비 클래스 로더를 가지고 스크립트를 컴파일하지 않는 경우
Class scriptClass = cl.parseClass(scriptSource);
Foo script = scriptClass.newInstance();
, 내가 얻을 :
문제는 주변 것으로 보인다 죽은 그루비 클래스 로더.
업데이트 :
누수의 원인이되는 코드를 찾았습니다.
Foo script = scriptClass.newInstance();
스크립트를 실행하려면 새 인스턴스를 만들어야하므로이를 수정하는 방법을 잘 모릅니다.
Java 8이 PermGen 문제를 제거하지 않았습니까? :) (실제로 이것이 왜 일어날 지에 대해서도 관심이 있습니다!) –
Java 8은 PermGen 공간을 Metaspace로 바꿨습니다.이 공간은 기본적으로 자동으로 확장됩니다. 그러나 Java 8은 실제 누수에 대해서는 아무 것도하지 않습니다. 여전히 OutOfMemoryError : Metaspace를 얻을 수 있습니다. 이유 및 방법을 읽고 싶다면 주제에 관한 블로그 시리즈를 확인하십시오. http://java.jiderhamn.se/2011/12/11/classloader-leaks-i-how -to-find-classloader-leaks-with-eclipse-memory-analyzer-mat/ –
현재 Java 8 로의 업그레이드는 현재로서는 실행 가능한 솔루션이 아닙니다.또한 Groovy를 업그레이드하면이 누수가 발생하는 이유는 해결되지 않습니다. – ColinMc