为了账号安全,请及时绑定邮箱和手机立即绑定

java.lang.OutOfMemoryError: unable to create new

java.lang.OutOfMemoryError: unable to create new

蝴蝶刀刀 2019-03-19 17:15:27
程序总是在两三天就报一次内存泄漏的异常,不知道是什么原因引起的,因为项目中有一个地方冲到队列,在队列中创建了很多的线程不知道是不是这个引起了。。。public class GlobalVariables {    public static ExecutorService pool = Executors.newFixedThreadPool(1000);    public static BlockingQueue<Object> queue = new ArrayBlockingQueue<Object>(1000);    public static Map<Integer, Integer> map = new HashMap<Integer, Integer>();    }public class AddQueues implements Runnable{    private Object obj;        public AddQueues(Object obj) {        this.obj = obj;    }    @Override    public void run() {        try {            System.out.println("-------------"+obj);            GlobalVariables.queue.put(obj);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}@Overridepublic Map<String, Object> updateQueuePool(Map<String, Object> map) throws Exception {        EntranceVisitCountDTO dto = new EntranceVisitCountDTO();        dto.setAdminUserId(Integer.parseInt(map.get("adminUserId").toString()));        GlobalVariables.pool.submit(new AddQueues(dto));        Map<String,Object> param = new HashMap<String,Object>();        param.put("result", "yes");                return param;    }/*** 定时将队列里的数据放到map中*/@Scheduled(cron = "0/3 * * * * ?")public synchronized void updateVisitCountOfMap(){    try{        if(!GlobalVariables.queue.isEmpty()){                    for(int i = 0; i < 100; i++){                Object obj = GlobalVariables.queue.take();                if(obj instanceof EntranceVisitCountDTO){                    EntranceVisitCountDTO dto = (EntranceVisitCountDTO)obj;                    Integer visitCount = GlobalVariables.map.get(dto.getAdminUserId());                    if(visitCount != null && GlobalVariables.map.size() <= 1000){                        GlobalVariables.map.put(dto.getAdminUserId(), visitCount +1);                    }else if(GlobalVariables.map.size() > 1000){                        visitDayCountService.updateEntranceShowCount();
查看完整描述

3 回答

?
缥缈止盈

TA贡献2041条经验 获得超4个赞

  1. 这段代码的入口应该是updateQueuePool方法,这个方法会生成DTO,然后创建新的job来吧DTO放到queue里面去,而这个queue的消费者是在updateVisitCountOfMap,这个方法每3秒钟消费100个DTO,如果调用updateQueuePooll方法的频率大于消费的频率的话,OOM是早晚的事情

  2. GlobalVariables.map也是类似的问题,每3秒放入最多100个对象,但是每10分钟消费。

  3. GlobalVariables的几个字段都是公开的,意味着任何代码都可以直接使用,这个也是个可能导致问题的因素。

  4. 如果内存有泄露,调用System.gc没任何帮助。

这段代码问题挺多的,不过不是完整代码,所以也不能确定哪个地方会有内存泄露,你最好让代码运行一段时间,然后用jmap dump下jvm,然后用virtual vm来查看该dump文件,看看到底是queue引用的对象还是map里面的对象没有被回收导致的。


查看完整回答
反对 回复 2019-04-18
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

unable to create new native thread'
很少有这种OOM,一定是代码那里不断的new Thread()造成的。
改成线程池吧。

查看完整回答
反对 回复 2019-04-18
?
Qyouu

TA贡献1786条经验 获得超11个赞

你设置的线程池大小是1000个,没必要建这么多吧,可以先看下主机是几核几线程,建议调低一点。另外jvm中的xxs分配多大,这个是影响你在jvm中能开多少线程的。在核查xmx的大小。


查看完整回答
反对 回复 2019-04-18
  • 3 回答
  • 0 关注
  • 631 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信