使用LinkedBlockingQueue时发生Java内存泄漏

使用LinkedBlockingQueue时发生Java内存泄漏,java,multithreading,memory-leaks,Java,Multithreading,Memory Leaks,亲爱的 我的java应用程序在运行一段时间后抛出一个异常 线程“thread-6”java.lang.OutOfMemoryError中出现异常:超出GC开销限制 在使用jprofiler监视jvm内存之后,我发现代码中存在内存泄漏 在我的程序中,我向一些设备发送了大量snmp请求,获取它们的响应,并将它们推送到两个LinkedBlockingQueue对象中。 有些线程从队列中轮询并处理它们,然后从队列中删除对象。但似乎这些对象并没有从队列中移除。我看不出我的代码有任何问题。 如有任何意见和建

亲爱的

我的java应用程序在运行一段时间后抛出一个异常

线程“thread-6”java.lang.OutOfMemoryError中出现异常:超出GC开销限制

在使用jprofiler监视jvm内存之后,我发现代码中存在内存泄漏

在我的程序中,我向一些设备发送了大量snmp请求,获取它们的响应,并将它们推送到两个LinkedBlockingQueue对象中。
有些线程从队列中轮询并处理它们,然后从队列中删除对象。但似乎这些对象并没有从队列中移除。我看不出我的代码有任何问题。 如有任何意见和建议,将不胜感激

ResponseListener.java
public class ResponseListener{
    public void receiveResponse(){
                SNMPResultMessage resultMessage;
                    resultMessage = new SNMPResultMessage(
                            userObject.getDeviceId(),
                            oid,
                            deviceServiceId,
                            sensorId,
                            response.getVariable(oid).toInt(),
                            userObject.getTimestamp(),
                            Utils.getCreateDay(dt),
                            Utils.getQuarterOfDay(dt),
                            slaDisabled
                    );
                    Logger.debug("SNMP Request Response:" + resultMessage);                    

                PubSub.publish(resultMessage);

     }
}
PubSub.java

公开课公开课{

public static final BlockingQueue<ResultMessage> average = new LinkedBlockingQueue<>();
public static final BlockingQueue<ResultMessage> cassandra = new LinkedBlockingQueue<>();
public static void publish(ResultMessage message) {
    average.add(message);
    cassandra.add(message);
}



private PubSub() {
    /* prevent instantiation */
}
在我的代码中,仅在ResponseListener.java中创建新的SNMPResultMessage对象。请查看附加的图像。

我猜队列已经满了,因为您插入新消息的速度比读取消息的速度快


请尝试检查队列的大小或使用。

insertBatch做什么?您使用的是什么版本的Java?一些早期版本没有正确地解除队列头的链接,从而无法清理节点。在cassandraWatcher中插入批将数据插入数据库,在averageWatcher中将数据插入mysql Java版本“1.8.0_60”Java(TM)SE运行时环境(构建1.8.0_60-b27)我正在docker Container上运行它,您确定它来自队列吗?您应该进行堆转储,找出所有数据的存放位置。错误不大可能在队列中,而不是在您的实现中。@jo您看到screnshoot了吗?为什么它会生成LinkedBlockingQueue实例?我只有一个类型的对象LinkedBlockingQueue
public class AverageWatcher implements Runnable{
    @Override
    public void run() {
        try {
            while (true) {
                ResultMessage message = PubSub.average.take();
                if (message == null) {
                    if (numberOfChanges > 1000) {
                        insertBatch();
                    }
                    continue;
                }
                numberOfChanges++;
                if (changes.get(message.getSensorId()) == null) {
                    changes.put(message.getSensorId(), new HashSet<>());
                }
                changes.get(message.getSensorId()).add(new CreateDayQuarterOfDay(message.getCreateDay(), message.getQuarterOfDay()));
                if (numberOfChanges > 5000) {
                    insertBatch();
                }
            }
        } catch (Exception ex) {
            Logger.error(ex.getCause());
        }
    }
}
public class CassandraQueueWatcher implements Runnable{
    @Override
    public void run() {
        try {
            while (true) {
                ResultMessage message = PubSub.cassandra.take();
                if (message == null) {
                    if (batchSize > 1000) {
                        insertBatch();
                    }
                    continue;
                }

                boolean violated = checkViolated(message);

                batch.add(
                        Cassandra.insertRawReportStmt
                                .bind()
                                .setInt("sensor_id", message.getSensorId())
                                .setInt("create_day", message.getCreateDay())
                                .setLong("create_time", message.getTimestamp() / 1000)
                                .setFloat("value", message.getValue())
                                .setBool("violated",violated)
                );
                batchSize++;
                if (batchSize > 2000) {
                    insertBatch();
                }
                message =  null;
            }
        } catch (Exception ex) {
            Logger.error(ex.getCause());
        }
    }

}