实战Java内存泄漏问题分析 -- hazelcast2.0.3使用时内存泄漏 -- 2

hazelcast 提供了3中方法调用startCleanup:

第一种是在ConcuurentMapManager的构造函数中,通过调用node的executorManager中的ScheduledExecutorService来创建每秒运行一次cleanup操作的线程(代码例如以下)。

因为这是ConcuurentMapManager构造函数的代码,所以这样的调用startCleanup的操作是默认就会有的。

node.executorManager.getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {publicvoid run() {for (CMap cMap : maps.values()) {cMap.startCleanup(false);}}}, 1, 1, TimeUnit.SECONDS);

另外一种是通过配置文件来触发startCleanup的运行。配置 PutOperationhandlerif overcapacity policy。我们系统的配置文件没有配置这方面的policy,全部这样的方式在我们系统中没有使用。

第三种是自己直接写代码去调用startCleanup函数(public方法。线程安全的). 这个没有实如今我们的系统中。


所以我的调查方向放在了第一种调用的情况,hazelcast里面的ScheduledExecutorService是通过java.util.ScheduledThreadPoolExecutor 来实现的.

esScheduled = new ScheduledThreadPoolExecutor(5, new ExecutorThreadFactory(node.threadGroup,node.getThreadPoolNamePrefix("scheduled"), classLoader), new RejectionHandler()) {protected void beforeExecute(Thread t, Runnable r) {threadPoolBeforeExecute(t, r);}}
查看ScheduledThreadPoolExecutor的实现,它把线程实现分成了3个部分: runnable tasks可运行任务, workers to execute the tasks运行任务的详细线程 以及 ScheduledThreadPoolExecutor 调度workers依照要求运行runnable tasks。

我们通过scheduleAtFixdRate提交了task,scheduleAtFixedRate先把它打包成反复运行的ScheduleFutureTask

<pre name="code" class="java">    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit) {if (command == null || unit == null)throw new NullPointerException();if (period <= 0)throw new IllegalArgumentException();RunnableScheduledFuture<?

> t = decorateTask(command, new <strong>ScheduledFutureTas</strong>k<Object>(command, null, triggerTime(initialDelay, unit), unit.toNanos(period))); delayedExecute(t); return t; }

 

ScheduleFutureTask的run方法实现又一次schedule:

public void  run() {boolean periodic = isPeriodic();if (!canRunInCurrentRunState(periodic))cancel(false);else if (!periodic)ScheduledFutureTask.super.run();else if (ScheduledFutureTask.super.runAndReset()) {setNextRunTime();<strong> reExecutePeriodic(outerTask);</strong>}
}
delayedExecute里面假设当前worker的数目小于初始化定义的CorePool的数目,就创建新的worker线程,然后把task放到queue里面

private void delayedExecute(Runnable command) {if (isShutdown()) {reject(command);return;}// Prestart a thread if necessary. We cannot prestart it// running the task because the task (probably) shouldn't be// run yet, so thread will just idle until delay elapses.if (getPoolSize() < getCorePoolSize())prestartCoreThread();<strong> super.getQueue().add(command);</strong>
} 
public boolean prestartCoreThread() {return addIfUnderCorePoolSize(null);}private boolean addIfUnderCorePoolSize(Runnable firstTask) {Thread t = null;final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {if (poolSize < corePoolSize && runState == RUNNING)t = addThread(firstTask);} finally {mainLock.unlock();}return t != null;}
private Thread addThread(Runnable firstTask) {Worker w = new Worker(firstTask);Thread t = threadFactory.newThread(w);boolean workerStarted = false;if (t != null) {if (t.isAlive()) // precheck that t is startablethrow new IllegalThreadStateException();w.thread = t;workers.add(w);int nt = ++poolSize;if (nt > largestPoolSize)largestPoolSize = nt;try {t.start();workerStarted = true;}finally {if (!workerStarted)workers.remove(w);}}return t;
}
全部启动的worker就做一件事情,从queue中取task运行

     try {hasRun = true;Runnable task = firstTask;firstTask = null;while (task != null || (task = <strong>getTask</strong>()) != null) {<strong>runTask(task);</strong>task = null;}} finally {workerDone(this);}}}Runnable getTask() {<strong> for (;;) {</strong>try {int state = runState;if (state > SHUTDOWN)return null;Runnable r;if (state == SHUTDOWN)  // Help drain queuer = workQueue.poll();else if (poolSize > corePoolSize || allowCoreThreadTimeOut)r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);else<strong> r = workQueue.take();</strong>if (r != null)return r;if (workerCanExit()) {if (runState >= SHUTDOWN) // Wake up othersinterruptIdleWorkers();return null;}// Else retry} catch (InterruptedException ie) {// On interruption, re-check runState}}
}
private void runTask(Runnable task) {final ReentrantLock runLock = this.runLock;runLock.lock();try {if ((runState >= STOP ||(Thread.interrupted() && runState >= STOP)) &&hasRun)thread.interrupt();boolean ran = false;beforeExecute(thread, task);<strong> try {task.run();ran = true;afterExecute(task, null);++completedTasks;} catch (RuntimeException ex) {if (!ran)afterExecute(task, ex);throw ex;}</strong>} finally {runLock.unlock();}}
了解了java threadpool的工作原理之后。我们能够知道。startCleanup是代码pass给ScheduledThreadPoolExecutor的runnable task,它不被运行,可能的原因有:

1. ScheduledThreadPoolExecutor初始化时候出错,task全然没有提交成功。因为lastCleanup并非系统应用的启动时间,已经过了几个月了,所以。非常明显在系统初始化的时候,esScheduled(ScheduledThreadPoolExecutor)还是正常工作的,仅仅是突然在2月4号停止了工作,所以这样的可能性能够排除。


2.    Worker 没有正常工作。不在从ScheduledThreadPoolExecutor的queue里面取数据,这个非常快就被我排除了:

首先heap dump中有5个pending workers in esScheduled (0/2/3/5/9):


其次从thread dump中能够看出,这五个线程都是在等着从queue里面取数据:

    ……<strong> at java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2025)[optimiz</strong>ed]at java/util/concurrent/DelayQueue.take(DelayQueue.java:164)[optimized]at java/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:609)[inlined]at java/util/concurrent/ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:602)[optimized]at java/util/concurrent/ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)[optimized]at java/util/concurrent/ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)at java/lang/Thread.run(Thread.java:662)at jrockit/vm/RNI.c2java(JJJJJ)V(Native Method)-- end of trace
hz._hzInstance_1_com.ericsson.ngin.session.ra.hazelcast.scheduled.thread-2" id=51 idx=0xd8 tid=32639 prio=5 alive, parked, native_blocked
hz._hzInstance_1_com.ericsson.ngin.session.ra.hazelcast.scheduled.thread-3" id=52 idx=0xdc tid=32640 prio=5 alive, parked, native_blocked
hz._hzInstance_1_com.ericsson.ngin.session.ra.hazelcast.scheduled.thread-4" id=53 idx=0xe0 tid=32641 prio=5 alive, parked, native_blocked
hz._hzInstance_1_com.ericsson.ngin.session.ra.hazelcast.scheduled.thread-5" id=75590 idx=0x3cc tid=3308 prio=5 alive, parked, native_blocked
所以worker不正常也被排除了。

3.  我们提交给系统的runner task自己主动从queue里面消失了,从memory dump中确实发现queue没有tasks了

而没有task的原因非常明显是由于当前task运行完之后没有又一次reschedule,至于原因,由于scheduledFutrueTask已经不存在,无法从memory dump和thread dump中分析出结果,成为了一个谜。。

。。

public void  run() {boolean periodic = isPeriodic();if (!canRunInCurrentRunState(periodic))cancel(false);else if (!periodic)ScheduledFutureTask.super.run();else if (ScheduledFutureTask.super.runAndReset()) {setNextRunTime();<strong> reExecutePeriodic(outerTask);</strong>}
}


转载于:https://www.cnblogs.com/liguangsunls/p/6898371.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372107.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

@SuppressLint(NewApi)和@TargetApi()的区别

转自&#xff1a;http://blog.csdn.NET/wbshuang09/article/details/44920549在Android代码中&#xff0c;我们有时会使用比我们在AndroidManifest中设置的android:minSdkVersion版本更高的方法&#xff0c;此时编译器会提示警告&#xff0c;解决方法是在方法上加上SuppressLin…

零基础自学编程前需要知道的知识

你是否适合编程?学习编程后能做什么?如何选择编程语言?有哪些免费的线上学习网站推荐?今天这篇好文将那些自学编程前需要了解和思考的问题都记录下来&#xff0c;希望能给那些刚刚开始或正准备自学编程的朋友们带去一些启发。 你是否适合自学编程 自学编程会是一个漫长而艰…

Eclipse设置黑色主题

1点击help--->install new software 2输入 http://eclipse-color-theme.github.com/update 3下载安装eclipse color theme插件如下图 4完成后点击windows--->preferences------>Appearance下多了一个Color Theme 5,点击选择喜欢的主题即可&#xff0c;也可以自己下载主…

wcf rest系列文章

http://www.cnblogs.com/artech/archive/2012/02/15/wcf-rest.html 需要注意的是&#xff0c;发布的服务&#xff0c;可以在web behavior中指定显示help页面。 http://localhost/ApplicationName/ServiceName.svc/help 需要注意的是&#xff0c;访问.svc的页面一定不要多加/;否…

登录:应用程序错误通知

几个月前&#xff0c;当我进行大型应用程序重构时&#xff0c;发现用于记录日志的基于log4j的代码确实令人讨厌&#xff0c;重复了数百次&#xff1a; if (LOG.isDebugEnabled()) {LOG.debug("Logging some stuff " stuff); }我想摆脱isXXXEnabled&#xff0c;这就…

如何分析线程转储–线程堆栈跟踪

本文是“ 线程转储”分析系列的第5部分。 到目前为止&#xff0c;您已经了解了线程的基本原理以及它们与Java EE容器和JVM的交互。 您还学习了HotSpot和IBM Java VM的不同线程转储格式。 现在是您深入分析过程的时候了。 为了使您能够从线程转储中快速识别问题模式&#xff0c;…

设计模式学习笔记(十三:原型模式)

1.1概述 用原型实例指定创建对象的种类&#xff0c;并且通过复制这些原型创建新的对象。这就是原型模式的定义。 在某些情况下&#xff0c;可能不希望反复使用类的构造方法创建许多对象&#xff0c;而是希望使用该类创建一个对象后&#xff0c;以该对象为原型得到该对象的若干个…

翻译的一篇关于学习编程语言的小文章

Top programming languages to get a job in Toronto in 2017 在程序开发人员和软件工程师中最容易被提及的问题之一就是&#xff1a;“我要学的下一门编程语言该是谁&#xff1f;” 我想去选一个编程语言&#xff0c;我希望你能给我一些关于经常使用到的编程语言的建议&#x…

从linux内核启动,学习Linux内核启动过程:从start_kernel到init

一、实验步骤&#xff1a;1&#xff1a;运行menuos&#xff1a;a)cd LinuxKernel/b)qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img启动后启动了MenuOS。2:使用gdb调试跟踪menuos内核启动和运行过程&#xff1b;a)qemu -kernel linux-3.18.6/arch/x86/bo…

linux强制回收内存,Linu系统cache强制回收

LINUX的内存管理机制&#xff0c;一般情况下不需要特意去释放已经使用的cache。Cache机制的存在&#xff0c;使得Linux对磁盘的读写速度是有较大的好处的。 在 Linux 操作系统中&#xff0c;当应用程序需要读取文件中的数据时&#xff0c;操作系统先分配一些内存&#xff0c;将…

Google API:如何访问Google Analytics(分析)数据?

在深入研究Google Analytics&#xff08;分析&#xff09;API之前&#xff0c;了解一些Google Analytics&#xff08;分析&#xff09;术语及其关系总是很有用的。 Google帐户&#xff1a;要访问Google Analytics&#xff08;分析&#xff09;&#xff0c;用户将需要一个Google…

设计模式学习笔记(十六:桥接模式)

1.1概述 将抽象部分与它的实现部分分离&#xff0c;使他们都可以独立地变化。这就是桥接模式的定义。 抽象类或接口中可以定义若干个抽象方法&#xff0c;习惯上将抽象方法称作操作。抽象类或接口使程序的设计者忽略操作的细节&#xff0c;即不必考虑这些操作是如何实现的&…

linux静默删除文件夹,Linux常用命令10 - unzip

zip 是最广泛使用的归档文件, 除了linux&#xff0c;windows也是非常的广泛。&#xff0c;支持无损数据压缩。 zip 文件是包含一个或多个压缩文件或目录的数据容器。接下来&#xff0c;我将解释如何使用 unzip 命令通过命令行解压缩 Linux 系统中的文件。 还有与之对应就是 zip…

python基础:迭代器、生成器(yield)详细解读

1. 迭代器 迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问&#xff0c;知道所有的元素被访问完结束。迭代器只能往前不会后退&#xff0c;不过这也没什么&#xff0c;因为人们很少在迭代途中往后退。 1.1 使用迭代器的优点 对于原生支持随机访问的数据…

Linux将硬盘转化为pv,Linux扩展硬盘 物理卷(PV) 卷组(VG) 逻辑卷(LV)

1、给虚拟机添加两块新的sata虚拟硬盘&#xff0c;容量8G和10G# fdisk -l 命令2、分别在这两个硬盘上建立pvPvcreate /dev/sdb 创建一个物理卷/dev/sdb 磁盘名是 fdisk -l 查询出来的Pvscan 查看当前所有物理卷Pvdisplay 查看当前所有物理卷的详情3、创建VG&#xff0c;使得…

ubuntu 16.10 shu rufa meiy ou l e geng xi zhi hou

转载于:https://www.cnblogs.com/ganmk--jy/p/6035894.html

红旗linux 进不去图形界面,进不了红旗Linux6.0的图形界面请高手帮忙

习生 于 2008-11-02 11:08:42发表:引用:原帖由 zhaoruiqi 于 2008-11-2 10:03 发表 我的也是进不了图形界面&#xff0c;用文本安装后进系统也一样正常按rtl的方法对xorg.conf进行修改,已经能进入图形界面。你看看楼上rtl的回复的能否对你有帮助。zhaoruiqi 于 2008-11-02 10:0…

基于Activiti工作流引擎实现的请假审核流程

概要 本文档介绍的是某商用中集成的Activiti工作流的部署及使用&#xff0c;该框架用的Activiti版本为5.19.0。本文档中主要以一个请假流程为例子进行说明&#xff0c;该例子的流程图如下&#xff1a; 这是一个可以正常运作的工作流业务了&#xff0c;但是它也有不足的地方&…

linux编译ffmpeg成so,「ffmpeg」一 mac 环境下编译ffmpeg,生成so库文件

1.下载ffmpeg源码,官网&#xff0c;我这里直接采用git 方式下载&#xff1a;下载ffmpeg.png终端输入git命令&#xff1a;静静等待~最后下载的版本为3.4.6 。image.png这里注意一下&#xff0c;刚开始我用的ndk版本是ndk-17b&#xff0c;在编译该版本的ffmpeg时始终失败&#xf…

Spring Security 3 Ajax登录–访问受保护的资源

我看过一些有关Spring Security 3 Ajax登录的博客&#xff0c;但是我找不到解决如何调用基于Ajax的登录的博客&#xff0c;匿名用户正在Ajax中访问受保护的资源。 问题 – Web应用程序允许匿名访问某些部分&#xff0c;并且某些部分是受保护的资源&#xff0c;需要用户登录。 …