우리는 jython을 사용하여 파이썬 스크립트를 실행하는 JavaEE 애플리케이션을 보유하고 있습니다. 사용 된 힙 스페이스는 더 이상의 힙 스페이스가 없어 질 때까지 점점 더 커집니다. heapdump에서 많은 Py * 클래스가 있다는 것을 알 수 있습니다.Java ScriptEngine (Jyhton)의 과도한 사용으로 힙이 증가합니다
disqualify = True
reason = "reason"
:
가 지정된 디렉토리에서 ScriptExecutor
public class ScriptExecutor {
private final static String pythonExtension = "py";
private final static String pythonEngine = "python";
private final ScriptEngine scriptEngine;
public ScriptExecutor(ScriptEngine se, File file, Map<String, Object> keyValues) throws FileNotFoundException, ScriptException {
scriptEngine = se;
if (keyValues != null) {
for (Map.Entry<String, Object> entry : keyValues.entrySet()) {
scriptEngine.put(entry.getKey(), entry.getValue());
}
}
// execute script
Reader reader = null;
try {
reader = new FileReader(file);
scriptEngine.eval(reader);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// nothing to do
}
}
}
}
public Boolean getBooleanScriptValue(String key) {
// convert Object to Boolean
}
public String getStringScriptValue(String key) {
// convert Object to String
}
public static String getEngineNameByExtension(String fileName) {
String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
if (pythonExtension.equalsIgnoreCase(extension)) {
System.out.println("Found engine " + pythonEngine + " for extension " + extension + ".");
return pythonEngine;
}
throw new RuntimeException("No suitable engine found for extension " + extension);
}
}
public class TestApp {
private final ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
private HashMap<String, ScriptEngine> scriptEngines = new HashMap<String, ScriptEngine>();
private final String scriptContainerPath = "";
public static void main(String[] args) throws InterruptedException {
int counter = 1;
while(true) {
System.out.println("iteration: " + counter);
TestApp testApp = new TestApp();
testApp.execute();
counter++;
Thread.sleep(100);
}
}
void execute() {
File scriptContainer = new File(scriptContainerPath);
File[] scripts = scriptContainer.listFiles();
if (scripts != null && scripts.length > 0) {
Arrays.sort(scripts, new Comparator<File>() {
@Override
public int compare(File file1, File file2) {
return file1.getName().compareTo(file2.getName());
}
});
for (File script : scripts) {
String engineName = ScriptExecutor.getEngineNameByExtension(script.getName());
if(!scriptEngines.containsKey(engineName)) {
scriptEngines.put(engineName, scriptEngineManager.getEngineByName(engineName));
}
ScriptEngine scriptEngine = scriptEngines.get(engineName);
try {
ScriptExecutor scriptExecutor = new ScriptExecutor(scriptEngine, script, null);
Boolean disqualify = scriptExecutor.getBooleanScriptValue("disqualify");
String reason = scriptExecutor.getStringScriptValue("reason");
System.out.println("disqualify: " + disqualify);
System.out.println("reason: " + reason);
} catch (Exception e) {
e.printStackTrace();
}
}
// cleanup
for(Map.Entry<String, ScriptEngine> entry : scriptEngines.entrySet()) {
ScriptEngine engine = entry.getValue();
engine.getContext().setErrorWriter(null);
engine.getContext().setReader(null);
engine.getContext().setWriter(null);
}
}
}
}
모두는 다음과 같이 14 파이썬 스크립트입니다 TestApp가 :
그래서 나는 작은 테스트 프로그램을 작성다음 VM 인수를 사용하여이 프로그램을 시작합니다. -Xrs -Xms16M -Xmx16M -XX : MaxPermSize = 32M -XX : NewRatio = 3 -Dsun.rmi.dgc.client.gcInterval = 300000 -Dsun.rmi.dgc.server.gcInterval = 300000 -XX : + UseConcMarkSweepGC -XX : + UseParNewGC -XX : + CMSParallelRemarkEnabled -verbose : gc -XX : + PrintGCDetails -XX : + PrintGCTimeStamps -server
다음은 AppServer가 실행되는 인수입니다. 내 테스트 케이스에서는 Xms, Xmx 및 MaxPermSize 만 작습니다.
이 응용 프로그램을 실행하면 CMS Old Gen 풀이 최대 크기로 증가한다는 것을 알 수 있습니다. 그 후에 Par Eden Space 풀이 증가합니다. 또한 언제든지 ParNewGC가 더 이상 실행되지 않습니다. 정리 부분은 상황을 개선했지만 문제를 해결하지 못했습니다. 내 힙이 완전하게 정리되지 않은 이유를 누구나 알고 있습니까?