值得阅读的内存泄露分析总结和Tomcat调优
虽然对内存泄露的研究有了明确的结果,可是tomcat占用内存持续升高得不到释放的问题还是没有答案。现在通过监控软件可以明确看到Heap的内存使用回收很正常,可是通过任务管理器监控看到的Tomcat占用内存却只升不减。 Tomcat是Java写的,运行在JVM之上,所以tomcat的使用的堆内存大小是不可能超过JVM定义的堆大小。所以Jprofile监控的Heap使用情况和从任务管理器看到Tomcat使用内存肯定不完全一样,除了堆内存肯定还有之外的内存。那么还有什么内存呢?上面介绍内存组成时有个直接内存,当发现还有直接内存这个东西时,感觉发生了新大陆一样,隐隐约约感觉问题的关键就在这里。 Part4.直接内存和NIO 又是一顿查资料了解直接内存和NIO相关的内容。根据官方文档的描述: A byte buffer is either direct ornon-direct. Given a direct byte buffer, the Java virtual machine will make abest effort to perform native I/O operations directly upon it. That is, it willattempt to avoid copying the buffer's content to (or from) an intermediatebuffer before (or after) each invocation of one of the underlying operatingsystem's native I/O operations. byte byffer可以是两种类型,一种是基于直接内存(也就是非堆内存);另一种是非直接内存(也就是堆内存)。 对于直接内存来说,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地系统的IO操作。而非直接内存,也就是堆内存中的数据,如果要作IO操作,,会先复制到直接内存,再利用本地IO处理。 从数据流的角度,非直接内存是下面这样的数据链: 本地IO-->直接内存-->非直接内存-->直接内存-->本地IO 而直接内存是: 本地IO-->直接内存-->本地IO 很明显,再做IO处理时,比如网络发送大量数据时,直接内存会具有更高的效率。 NIO(New IO)是基于基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区,或者从缓冲区写到通道中。具体信息有兴趣可以自行上网查。 这个时候突然看到一个帖子里的回复说Tomcat8默认通信方式就是采用NIO方式,这个时候感觉看到希望之光了,立马就去看哪里用到了了NIO。后来在tomcat-coyote.jar中找到了,这个coyote是用来处理Tomcat底层的socket,并将http请求、响应等字节流层面的东西,包装成Request和Response两个类,供容器使用。所以意味着每一个前端请求都会经过这个处理了。下图源码中被圈中的代码就是分配直接内存的代码。 我们再点进去可以看到在jdk的源码中分配直接内存有个reserveMemory的函数,在每次分配直接内存的时候都会执行这个清理函数,然后再点进去有个大发现,在这个清理内存函数里面居然有手动调用gc的代码。 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |