【发布时间】:2017-06-22 07:51:56
【问题描述】:
我正在使用Formscanner,它在处理一些图像后给出了错误:
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:950)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1357)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
at com.albertoborsetta.formscanner.api.FormTemplate.findPoints(FormTemplate.java:852)
at com.albertoborsetta.formscanner.model.FormScannerModel.analyzeFiles(FormScannerModel.java:562)
at com.albertoborsetta.formscanner.main.FormScanner.main(FormScanner.java:145)
找点方法如下:
public void findPoints(BufferedImage image, int threshold, int density,
int size) throws FormScannerException {
height = image.getHeight();
width = image.getWidth();
int cores = Runtime.getRuntime().availableProcessors();
ExecutorService threadPool = Executors.newFixedThreadPool(cores - 1);
HashSet<Future<HashMap<String, FormQuestion>>> fieldDetectorThreads = new HashSet<>();
HashMap<String, FormQuestion> templateFields = template.getFields();
ArrayList<String> fieldNames = new ArrayList<>(templateFields.keySet());
Collections.sort(fieldNames);
for (String fieldName : fieldNames) {
Future<HashMap<String, FormQuestion>> future = threadPool.submit(new FieldDetector(threshold, density, size, this, templateFields.get(fieldName), image));
fieldDetectorThreads.add(future);
}
for (Future<HashMap<String, FormQuestion>> thread : fieldDetectorThreads) {
try {
HashMap<String, FormQuestion> threadFields = thread.get();
for (String fieldName : threadFields.keySet()) {
FormQuestion field = threadFields.get(fieldName);
fields.put(fieldName, field);
for (Entry<String, FormPoint> point : field.getPoints().entrySet()) {
if (point.getValue() != null) {
pointList.add(point.getValue());
}
}
}
} catch (InterruptedException | ExecutionException e) {
throw new FormScannerException(e.getCause());
}
}
threadPool.shutdown();
}
上面的函数在循环中被调用并且java进程的数量增长并且在某个点上它引发了上面的异常。
在调用关闭方法后,这些线程是否会被杀死。我不是Java开发人员。我做了一些研发。但我没有成功。
【问题讨论】:
-
您运行的是 32 位还是 64 位 JVM?使用的操作系统是什么?内存设置是什么(Xmx、Xms、Xss...)?
-
假设池限制了运行的线程数,并且您有一个
thread.get等待每个线程结束。因此,除非您在新线程中调用此方法(这将在堆栈跟踪中可见),否则我看不出这会如何重载。 当然,它可能是第一个运行的 FieldDetectors 实例,它会占用所有可用内存。 FieldDetector 实例会做什么? -
我使用 ubuntu 64bit 和 openjdk
-
@AxelH 我不知道。
-
我看到你在他们的谷歌论坛上发布了一个问题。在那里搜索,我注意到有一个帖子here 谈论只有在应用程序关闭时才清理内存使用的问题。所以我会说API有内存泄漏,以前的文件没有正确释放,导致你在很多文件处理后出现问题。它是开源的,所以如果你有时间,我可以在这个周末尝试检查源代码。我现在对 OMR 很好奇 ;)
标签: java multithreading pid