OutOfMemoryError - 控制台中没有跟踪

时间:2015-01-12 08:08:55

标签: java out-of-memory

在从ExecutorService将它放入Callable(带有其他几个Callable任务)之后,我调用下面的testMethod。我怀疑,map.put()会遇到OutOfMemoryError,因为我试图输入大约2000万个条目。

但是,我无法在控制台中看到错误跟踪。只是线程停止了。我试图捕捉错误(我知道..我们不应该,但我收集的调试)。但是,错误没有被发现。直接进入最后并停止执行..线程静止不动。

  private HashMap<String, Integer> testMethod(
        String file   ) { 
try {
        in = new FileInputStream(new File(file));
        br = new BufferedReader(new InputStreamReader(in), 102400);
        for (String line; (line= br.readLine()) != null;) {
            map.put(line.substring(1,17),
                    Integer.parseInt(line.substring(18,20)));
        }
        System.out.println("Loop End"); // Not executed

    } catch(Error e){
        e.printStackTrace(); //Not executed
    }finally {
        System.out.println(map.size()); //Executed
        br.close();
        in.close();
        }
return map;
}

这可能是错误,我在做什么?

编辑:这就是我执行线程的方式。

Callable<Void> callable1 = new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                testMethod(inputFile);
                return null;
            }
        };

        Callable<Void> callable2 = new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                testMethod1();
                return null;
            }
        };



        List<Callable<Void>> taskList = new ArrayList<Callable<Void>>();
        taskList.add(callable1);
        taskList.add(callable2);


        // create a pool executor with 3 threads
        ExecutorService executor = Executors.newFixedThreadPool(3);
        List<Future<Void>> future = executor.invokeAll(taskList);

        //executor.invokeAll(taskList);
        latch.await();

future.get(0);future.get(1); //Added this as per SubOptimal'sComment

但是,这个future.get()没有在控制台中显示OOME。

2 个答案:

答案 0 :(得分:2)

提交Callable后,你不应该抛弃未来。

Future future = pool.submit(callable);
future.get(); // this would show you the OOME

示例基于请求者的信息来演示

public static void main(String[] args) throws InterruptedException, ExecutionException {
    Callable<Void> callableOOME = new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            System.out.println("callableOOME");
            HashMap<String, Integer> map = new HashMap<>();
            // some code to force an OOME
            try {
                for (int i = 0; i < 10_000_000; i++) {
                    map.put(Integer.toString(i), i);
                }
            } catch (Error e) {
                e.printStackTrace();
            } finally {
                System.out.println("callableOOME: map size " + map.size());
            }
            return null;
        }
    };

    Callable<Void> callableNormal = new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            System.out.println("callableNormal");
            // some code to have a short "processing time"
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException ex) {
                System.err.println(ex.getMessage());
            }
            return null;
        }
    };

    List<Callable<Void>> taskList = new ArrayList<>();
    taskList.add(callableOOME);
    taskList.add(callableNormal);

    ExecutorService executor = Executors.newFixedThreadPool(3);
    List<Future<Void>> future = executor.invokeAll(taskList);

    System.out.println("get future 0: ");
    future.get(0).get();
    System.out.println("get future 1: ");
    future.get(1).get();
}

答案 1 :(得分:1)

尝试捕获Throwable,因为它可能是异常,如IOException或NullPointerException,Throwable捕获除System.exit()之外的所有内容;

另一种可能性是线程没有死亡,而是由于几乎耗尽内存但从不放弃而变得越来越慢。您应该可以通过堆栈转储或在运行时使用jvisualvm来查看此内容。

BTW除非所有字符串都长度为16个字符,否则您可能希望调用trim()来删除字符串中的任何填充。这可以缩短它们并减少使用内存。

我假设您使用的是最新版本的Java 7或8.如果您使用的是Java 6或更早版本,则会使用更多内存,因为.substring()不会创建新的基础{{1}保存CPU,但在这种情况下浪费内存。