JVM-内存分配与回收

1、内存分布web

Java虚拟机所管理的内存将会包括如下几个运行时数据区域,以下图所示:算法

本地方法栈数组

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的做用是很是类似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并无强制规定,所以具体的虚拟机能够自由实现它。甚至有的虚拟机(譬如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与缓存

虚拟机栈同样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。安全

(我的理解:虚拟机栈就是一般所说的栈,本地方法栈服务于native方法)数据结构

运行时常量池并发

运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各类字面量和符号引用,这部份内容将在类加载后存放到方法区的运行时常量池中。框架

直接内存(Direct Memory)jvm

直接内存并非JVM管理的内存,但这部份内存常常被使用,也可能致使OutOfMemoryError异常。函数

JDK中有一种基于通道(Channel)和缓冲区(Buffer)的I/O方式,将由C语言实现的native函数库直接分配堆外内存,用存储在JVM堆中的DirectByteBuffer来引用。因为直接内存收到本机器内存的限制,因此也可能出现OutOfMemoryError的异常。

2、须要回收的区域和对象

回收区域:堆和方法区

如何判断一个对象已死(便可回收对象),通常有引用计数算法和可达性分析算法

一、引用计数算法:每一个对象都有一个引用计数器,每当有一个地方引用它时计数器就加1,引用失效时计数器就减1,当计数器为0时,该对象就能够回收。缺点是循环引用对象不能被回收。

二、可达性分析算法:一系列“GC ROOTs”的对象做为起点,当某个对象与GC ROOTS不可达时,该对象即被判断为可回收对象。能够做为GC ROOTs对象的有如下几种:

三、扩充的引用

引用分为四种:(不会被回收的,可回收也可不回收,确定会被回收、不须要理会的)

  a> 强引用(Strong Reference).就是为刚被new出来的对象所加的引用,它的特色就是,永远不会被回收。

  b> 软引用(Soft Reference).声明为软引用的类,是可被回收的对象,若是JVM内存并不紧张,这类对象能够不被回收,若是内存紧张,则会被回收。此处有一个问题,既然被引用为软引用的对象能够回收,为何不去回收呢?其实咱们知道,Java中是存在缓存机制的,就拿字面量缓存来讲,有些时候,缓存的对象就是当前无关紧要的,只是留在内存中若是还有须要,则不须要从新分配内存便可使用,所以,这些对象便可被引用为软引用,方便使用,提升程序性能。

 c> 弱引用(Weak Reference).弱引用的对象就是必定须要进行垃圾回收的,无论内存是否紧张,当进行GC时,标记为弱引用的对象必定会被清理回收。

 d> 虚引用(Phantom Reference).虚引用弱的能够忽略不计,JVM彻底不会在意虚引用,其惟一做用对象被回收时会收到一些通知。

四、对象回收处理过程

对象被回收前须要进行两次标记过程。第一次是对象与GC Roots间不可达,即被第一次标记而且筛选该对象是否有必要执行finalize()方法,将筛选的对象放到一个执行队列中,没有必要执行finalize方法的对象会被回收;第二次仅对队列中的对象进行标记,若是在执行finalize方法中将对象与GC ROOTS关联上,则该对象将不会被回收,不然该对象将被回收。

3、内存分配

Java内存分配和回收的机制归纳的说,就是:分代分配,分代回收。对象将根据存活的时间被分为:年轻代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation,也就是方法区)

年轻代(Young Generation):对象被建立时,内存的分配首先发生在年轻代(大对象能够直接 被建立在年老代),大部分的对象在建立后很快就再也不使用,所以很快变得不可达,因而被年轻代的GC机制清理掉(IBM的研究代表,98%的对象都是很快消 亡的),这个GC机制被称为Minor GC或叫Young GC。注意,Minor GC并不表明年轻代内存不足,它事实上只表示在Eden区上的GC。

年轻代上的内存分配是这样的,年轻代能够分为3个区域:Eden区(伊甸园,亚当和夏娃偷吃禁果生娃娃的地方,用来表示内存首次分配的区域,再 贴切不过)和两个存活区(Survivor 0 、Survivor 1)。内存分配过程为:

  1. 绝大多数刚建立的对象会被分配在Eden区,其中的大多数对象很快就会消亡。Eden区是连续的内存空间,所以在其上分配内存极快;
  2. 当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的);
  3. 此后,每次Eden区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0;
  4. 当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,之后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的)。
  5. 当两个存活区切换了几回(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)以后,仍然存活的对象(其实只有一小部分,好比,咱们本身定义的对象),将被复制到老年代。

 

年老代(Old Generation):对象若是在年轻代存活了足够长的时间而没有被清理掉(即在几回 Young GC后存活了下来),则会被复制到年老代,年老代的空间通常比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。当年老代内存不足时, 将执行Major GC,也叫 Full GC。

 

4、垃圾收集算法

一、标记-清除算法

分两个阶段,标记阶段和清除阶段。首选标记出全部须要回收的对象,标记完成后统一回收全部被标记的对象。

二、复制算法

将内存分为大小相等的两块,每次只使用其中一块。当一块内存用完了,就将活着的对象复制到另外一块上面,最后一次性清除已使用过的内存空间。(通常新生代采用这种算法)

三、标记-整理算法

也是分为两个阶段。第一个阶段是标记,第二个阶段是将全部存活对象移动到一端,而后直接清理掉边界之外的内存。

四、分代收集算法

根据对象存活时间不一样将内存分为几部分。通常将堆分为新生代和年老代,根据年代的特色采用最适合的收集算法。例如,新生代通常采用复制算法,年老代采用标记-清除或者标记-整理算法。

5、JVM经常使用内存参数设置

a: -Xmx<n> 

指定 jvm 的最大 heap 大小 , 如 :-Xmx=2g 

 

b: -Xms<n> 

指定 jvm 的最小 heap 大小 , 如 :-Xms=2g , 高并发应用, 建议和-Xmx同样, 防止由于内存收缩/忽然增大带来的性能影响。 

 

c: -Xmn<n> 

指定 jvm 中 New Generation 的大小 , 如 :-Xmn256m。 这个参数很影响性能, 若是你的程序须要比较多的临时内存,建议设置到512M, 若是用的少, 尽可能下降这个数值, 通常来讲128/256足以使用了。 

 

d: -XX:PermSize=<n> 

指定 jvm 中 Perm Generation 的最小值 , 如 :-XX:PermSize=32m。 这个参数须要看你的实际状况,。能够经过jmap 命令看看到底须要多少。 

 

e: -XX:MaxPermSize=<n> 

指定 Perm Generation 的最大值 , 如 :-XX:MaxPermSize=64m 

 

f: -Xss<n> 

指定线程桟大小 , 如 :-Xss128k, 通常来讲,webx框架下的应用须要256K。 若是你的程序有大规模的递归行为,请考虑设置到512K/1M。 这个须要全面的测试才能知道。 不过,256K已经很大了。 这个参数对性能的影响比较大的。 

 

g: -XX:NewRatio=<n> 

指定 jvm 中 Old Generation heap size 与 New Generation 的比例 , 在使用 CMS GC 的状况下此参数失效 , 如 :-XX:NewRatio=2 

 

h: -XX:SurvivorRatio=<n> 

指 定 New Generation 中 Eden Space 与一个 Survivor Space 的 heap size 比例 ,-XX:SurvivorRatio=8, 那么在总共 New Generation 为 10m 的状况下 ,Eden Space 为 8m 

 

i: -XX:MinHeapFreeRatio=<n> 

指定 jvm heap 在使用率小于 n 的状况下 ,heap 进行收缩 ,Xmx==Xms 的状况下无效 , 如 :-XX:MinHeapFreeRatio=30 

 

j: -XX:MaxHeapFreeRatio=<n> 

指定 jvm heap 在使用率大于 n 的状况下 ,heap 进行扩张 ,Xmx==Xms 的状况下无效 , 如 :-XX:MaxHeapFreeRatio=70 

 

k: -XX:LargePageSizeInBytes=<n> 

指定 Java heap 的分页页面大小 , 如 :-XX:LargePageSizeInBytes=128m 

 

6、内存分配与回收策略

对象优先在Eden分配;

大对象直接进入老年代;(例如:长字符串和数组)

长期存活的对象将进入老年代;(Survivor空间中通过必定次数minor GC仍旧存活的对象)

动态对象年龄断定;(Survivor空间中对象不必定非等到必定年龄才能移动到年老代,也能够经过相同年龄对象总大小大于Survivor空间的一半,该年龄及以上大小的对象都被移动到年老代)

空间分配担保;(根据年老代上的最大可用连续空间是否大于整个新生代对象的空间,若是大于能够确保是安全的,能够直接minor GC;若是不是根据状况选择minor GC仍是full GC)

相关文章
相关标签/搜索