JVM虚拟机---(4)内存分配

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq1021979964/article/details/96100706

内存分配

JDK1.7之前,JVM将内存分为三个区域:新生代,老年代,永久代。

一、新生代(Young Generation)

       新生代的目标是尽可能快速收集那些生命周期短的对象,一般情况下,所有新生成的对象首先都是放在新生代的。

使用流程:

  1. 当Eden区满时,会触发young gc,将存活的对象复制到From区,当Eden区再次触发young gc,会扫描Eden区和From区,进行垃圾回收,将存活的对象复制到To区,并将Eden区和Fron区清空。
  2. 当后续Eden又触发young gc时,会对Eden区和To区进行垃圾回收,将存活的对象复制到From区,并将Eden区和Tao区清空。
  3. 存活的对象会一直在From和To重复复制,某个对象复制达到15次之后,依旧是存活的,将存入老年代。

注:如果存活的对象比较多,To区的内存不够存放,会借助老年代的空间。

新生代触发的GC叫做MinorGC,对象存活时间段,发生频率高。

新生代内存划分:Eden(伊甸园)、2块Survivor Space(存活区),比例是:8:1:1。

设置-XX:MaxTenuringThreashold参数,可以配置From与To的交换次数。默认15.

设置-XX:SerivorRation参数,可以配置Eden和Servivor比例。默认8.

 

二、老年代(Old Generation)

老年代存放的都是一些生命周期较长的对象,一般是在新生代进行多次垃圾回收之后依旧存活的对象会放到老年代。

老年代触发的GC叫做Full GC,对象存活时间长,发生频率较低。

设置-XX:pertenureSizeThreashold参数,可以将大于该值的对象直接放到老年代不经过新生代。

 

三、永久代(Permanent Generation)

       永久代主要用于存放静态文件,如Java类、方法等。永久代对垃圾回收没有显著 影响,但是有些应用可能动态生成或者调用一些Class,例如使用反射、动态代理、CGLib等bytecode框架时,这时需要设置比较大的永久代空间来存放这些运行过程中新增的类。

注:在JDK1.8的时候废弃了永久代,因为java提供了与永久代类似的叫做“元空间”的技术。

四、废弃永久代的原因

       由于永久代内存经常不够用,或发生内存泄露,抛出异常OutOfMemoryError。元空间的本质与永久代类似,但元空间与永久代之间最大的区别在与:元空间不在虚拟机,而是在本地内存,也就是不局限与JVM可以使用系统的内存,理论上取决于32位/64位系统可虚拟的内存大小。

五、代码演示

package com.kevin.jvm.memory;



/**

 * @author caonanqing

 * @version 1.0

 * @description     演示内存分配

 *

 *      设置参数:

 *          -verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M

 * @createDate 2019/7/13

 */

public class MemoryTest {



    public static void main(String[] args) {



        byte[] b1 = new byte[2*1024*1024];

        byte[] b2 = new byte[2*1024*1024];

        byte[] b3 = new byte[2*1024*1024];

        byte[] b4 = new byte[4*1024*1024];



        System.gc();

    }

}

六、内存分配参数选项

  • 堆内存参数

-Xms:表示java虚拟机堆区内存初始内存分配的大小,通常为操作系统可用内存的1/64大小即可
-Xmx:表示java虚拟机堆区内存可被分配的最大上限,通常为操作系统可用内存的1/4大小。
-XX:MinHeapFreeRatio:设置堆空间的最小空间比例。当堆空间的空闲内存小于这个数值时,jvm便会扩展堆空间。
-XX:MaxHeapFreeRatio:设置堆空间的最大空间比例。当堆空间的空闲内存大于这个数值时,jvm便会缩小堆空间。
-XX:NewSize : 设置新生代的大小
-XX:NewRatio:设置老年代与新生代的比例,即老年代除以新生代大小
-XX:SurviorRatio:新生代中eden区与survivior 区的比例
-XX:TargetSurvivorRatio:设置survivior 的使用率。当达到这个空间使用率时,会将对象送入老年代。
-Xmn:该参数是对-XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过-Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn。

但是开发过程中,通常会将 -Xms 与 -Xmx两个参数的配置相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源。

(如果初始堆内存满了,会尝试进行GC,如果GC后得不到足够的内存,便会扩展堆内存,这时,如果-Xmx设置太小,扩展堆则失败,会抛出OutOfMemoryError错误提示)。

通常开发中只需要对以上-Xms 与 -Xmx两个参数进行合理配置。

  • 方法区参数配置

-XX:PermSize:表示非堆区初始内存分配大小,其缩写为permanent size(持久化内存)
-XX:MaxPermSize:表示对非堆区分配的内存的最大上限
  • 栈容量配置

-Xss:设置线程栈的大小
  • 本机直接内存配置

-XX:MaxDirectMemorySize :指定本机直接内存大小,如果不指定就表示和Java堆最大值(-Xmx)相同。

猜你喜欢

转载自blog.csdn.net/qq1021979964/article/details/96100706