转载请注明出处 http://www.paraller.com
原文排版地址 点击获取更好阅读体验java
但垃圾收集效果难以使人满意:针对常量池的回收以及类的卸载(十分苛刻)web
当Old区再被塞满,就会触发FullGC,回收最后能回收的空间算法
局部变量表的内存空间在编译期就已经分配完成sql
发挥的做用与jvm stack相同,可是为虚拟机使用到的Native方法服务,hotspot虚拟机将两个合而为一数据库
java程序经过栈上的reference数据操做 堆上的 具体对象windows
虚拟机栈中reference数据称为引用
reference类型的数据中储存的数值表明的是另一块内存的起始地址,就称这块内存是表明着引用
除了 被引用和不被引用两种状态 ;JDK1.2以后引入了四种新的概念:强引用、软引用、弱引用、虚引用数组
主流的方式有两种,直接指针和使用句柄服务器
访问句柄: reference中保存着对象的具体地址。优势是快速。多线程
主要存放类信息,经过CGLib动态构造类会形成OOM异常,好比jsp的构造oracle
每当有一个地方引用+1 ,计数器为0说明没有对象引用它 , 存在两个无用对象相互引用的状况
主流方式;以GC Roots对象为起点,根据是否有引用链可达判断;哪些能够称为引用链:
PS
:对象如何在被标记回收的时候逃脱: 覆写finalize方法,将this赋值给某个类变量或者对象的成员变量
指某些对象再也不被应用程序使用,而垃圾收集器(Garbage Collector)却没能识别它们是“再也不使用的”。若是那些不使用的对象占用堆(heap)空间足够大,使得应用程序没法知足下一次内存分配需求,就会致使OutOfMemoryError错误
内存不够用了,缘由有几种,内存泄露只是其中一种。
通常是 OutOfMemoryError :先肯定是内存溢出仍是内存泄露(垃圾回收处理机制)
内存泄露:经过工具查看泄露对象到GC Roots的引用链,找到没法回收的缘由
内存溢出:调到物理内存,判断是否对象生命周期过长
线程请求的栈深度大于虚拟机栈所容许的最大深度;单线程的时候,不管是栈帧太大仍是虚拟机栈容量过小,当内存没法分配的时候,虚拟机抛出的都是这个异常
它保存了Java类定义,而且这些类定义是不会变成“无用”的,是吗?事实上,它们是能够变成“无用”的。以一个部署到应用程序服务器的Java web程序来讲,当该应用程序被卸载的时候,你的EAR/WAR包中的全部类都将变得无用。只要应用程序服务器还活着,JVM将继续运行,可是一大堆的类定义将再也不使用,理应将它们从永久代(PermGen)中移除。若是不移除的话,咱们在永久代(PermGen)区域就会有内存泄漏。
类加载器(classloader)泄漏的一个可能的场景就是经过运行的线程(而内存泄漏)。当你的程序,或者你的程序使用的第三方库(我常常遇到这种状况,好比Quartz)开启了一些长时间运行的线程。一个例子:一个用于周期性执行代码的计时器(timer)线程。
若是不解决该线程预期的生命周期问题,咱们直接会遇到麻烦。当你程序的任何一部分启动一个线程的时候,你要确保它不会比程序活得还要久。在典型的状况下,开发者要么不知道本身有责任处理好这个问题,或者忘了写清理(clean-up)的代码。
不然,若是应用程序卸载后,线程还在继续运行,它一般将维持一个到web应用程序的classloader的引用,即咱们所说的contextclassloader。这也就意味着,全部卸载掉的应用程序仍然保存在内存中。怎么解决?若是是你的程序开启了新线程,那么你就应该在卸载的时候关闭它们,这能够经过使用一个servlet context listener来实现。若是是第三方库开启的新线程,你应该搜索它的关闭线程的接口,若是没有的话,就上报一个bug吧。
另外一个典型的内存泄漏缘由是由数据库驱动形成的。咱们在和Plumbr一块儿发布的demo程序中遇到了这种内存泄漏状况。它是一个与Sprint MVC一块儿发布的、代码稍微修改过的Pet Clinic程序。让咱们关注一下当这个应用程序部署到服务器上的时候,发生了什么:
如今,当从服务器上卸载应用程序的时候,java.sql.DriverManager仍将持有那个引用,不管在HSQLDB库,或者在Spring framework中,都没有代码能够移除它!正如上面解释的那样,一个jdbcDriver对象将持有一个到org.hsqldb.jdbcDriver类的引用,从而持有用于加载应用程序的java.lang.Classloader的一个实例的引用。这个classloader如今仍然引用着应用程序的全部类。在咱们那特殊的demo应用程序中,在程序启动的时候,须要加载将近2000个类,占用约10MB永久代(PermGen)内存。这就意味着须要5~10次从新部署,才会将默认大小的永久代(PermGen)塞满,而后就会触发java.lang.OutOfMemoryError: PermGen space错误并崩溃。
怎样解决此问题?一个可能的办法就是写一个servlet content listener,用于在应用程序关闭的时候,从DriverManager反注册HSQLDB驱动。这个方法很直接,可是请记住——你须要在使用该驱动的每个应用程序中都这么写。
你的应用程序遇到java.lang.OutOfMemoryError: PermGen space错误的缘由不少,究其根本缘由,大多数是因为object或程序的class loader加载的类的引用已经无用了致使的。对此类问题,你须要采起的补救措施都很是类似,即,首先,找出引用在哪里被持有;其次,给你的web应用程序添加一个关闭的hook,或者在应用程序卸载后移除引用。你要么经过servlet context listener,要么经过第三方库提供的API来实现这一点。
非jvm运行时数据区;新加入了的NIO类,引入了"Channel"与"Buffer"的I/O方式
经过本地函数库分配一个堆外内存,而后经过java堆的的对象实例buffer做为这块内存的引用进行操做,由于避免了再java heap and native heap之间
进行复制操做,显著的提升性能,当对于jvm的各个内存总和大于直接内存会报错
句柄:简而言之数据的地址须要变更,变更之后就须要有人来记录管理变更,(就好像户籍管理同样),所以系统用句柄来记载数据地址的变动
Presenting the Permanent Generation
[[原创](翻译)什么是Java的永久代(PermGen)内存泄漏](http://ju.outofmemory.cn/entr...