基础知识之jvm内存空间

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014679456/article/details/83316850

Java基础知识之jvm内存空间

1 JVM内存空间有哪些分区?

  1. 方法区
  2. JAVA虚拟机栈
  3. 程序计数器
  4. 本地方法栈
    jvm1
    jvm图2
  • 堆空间(HEAP):是创建对象的实例和数组都存放的内存空间,是随着虚拟机的启动而创建的,它是线程共享的区域,所以操作共享区域的成员就有了锁和同步。一个jvm只拥有一个这样的空间,同时它是gc的主要回收区。它分为三个部分:新生代、老生代、永久代。如果再细致一点,Java Heap的新生代还有Eden空间,From Survivor空间,To Survivor空间。Java Heap可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。如下图所示。
    HEAP① 新生代
    新生代是类的诞生、成长、消亡的区域,大部分类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生代又分为两部分:伊甸园(Eden space)和幸存者区(Survivor pace),所有的类都是在伊甸园被new出来的。幸存区有两个为什么要用两个?:0区(Survivor 0 space)和1区(Survivor 1 space)。当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园进行垃圾回收(Minor GC),将伊甸园中的剩余对象移动到幸存0区。若幸存0区也满了,再对该区进行垃圾回收,然后移动到1区。那如果1去也满了就放入0区。默认迭代15次后对象移动到老年代。若养老区也满了,那么这个时候将产生Major GC(FullGCC),进行养老代的内存清理。若养老代执行Full GC 之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”。
    如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有:
    a.Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。
    b.代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。
    ② 养老代
    养老代用于保存从新生代筛选出来的 JAVA 对象,一般池对象都在这个区域活跃。
    ③ 永久代
    永久代是一个常驻内存区域,用于存放JDK自身所携带的 Class,Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭 JVM 才会释放此区域所占用的内存。
    如果出现java.lang.OutOfMemoryError: PermGen space,说明是Java虚拟机对永久代Perm内存设置不够。原因:
    a. 程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。
    b. 大量动态反射生成的类不断被加载,最终导致Perm区被占满。
    说明:
    Jdk1.6及之前:常量池分配在永久代 。
    Jdk1.7:有,但已经逐步“去永久代” 。
    Jdk1.8及之后:无(java.lang.OutOfMemoryError: PermGen space,这种错误将不会出现在JDK1.8中)。
    HEAP1.8

  • 方法区(Method Area):是各个线程共享的内存区域,它用于存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。常量池:(Constant Pool)是方法区的一部分,Class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量池中存放。静态变量+常量+类信息+运行时常量池存在方法区中,实例变量存在堆内存中。

  • JVM虚拟机栈(Stack):它是线程安全的,它的生命周期和线程一样。它描述的是一个java方法执行内存模型。每个方法执行过程钟都会创建一个栈帧(Frame)用来存储局部变量表、操作数栈、动态链接、方法出口。每个线程在执行一个方法时,都意味了有一个当前栈帧在进栈和出栈。局部变量表存放了编译时期的各种基本数据类型,对象引用。

  • 本地方法栈(Native Stack):与Java虚拟机站(Java Stack)所发挥的作用非常相似,他们之间的区别在于虚拟机栈为虚拟机栈执行java方法(也就是字节码)服务,而本地方法栈则为使用到Native方法服务。

  • 程序计数器(PC):指令执行的顺序就是PC寄存器在管,它的作用就是控制程序指令的执行顺序。

总结

  • 线程私有的数据区域有:
    Java虚拟机栈(Java Stack)
    本地方法栈(Native Stack)
    程序计数器
  • 线程共有的数据区域有:
    堆(Java Heap)
    方法区

猜你喜欢

转载自blog.csdn.net/u014679456/article/details/83316850