一、堆的体系结构

Heap 堆一个JVM 实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类字节码文件后,需要把类、方法、常量、变最放到堆内存中,保存所有引用类型的真实信息,以便执行器执行。
堆内存分为三部分:

  • Young Generation space 新生区 Young/New
  • Tenure generation space 养老区 Old/Tenure
  • Permanent space 永久代 Perm(JDK1.8 修改为MetaSpace,该区域从JVM的堆内存中移动到系统的本地内存;既JDK1.8的堆体系结构=新生代+老年代+MetaSpace),永久代在逻辑上在堆内存空间,但在物理上永久代与堆是独立的。方法区是规范,JVM的永久代是实现,元空间也是方法区的一个实现

新生区:新生区是类的诞生、成长、消亡的区域,一个类在该这产生、应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:伊甸区(Eden space)和两个幸存者区(Survivor Space) 或者是Survivor  form 和 Survivor  to,所有的类都是在伊甸区被new 出来的。当伊甸园的空间用完时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC ) ,在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。若老年代也满了,那么这个时候将产生 Major GC(Full GC),进行老年代的内存清理。若老年代执行了Full GC之后发现依然无法释放足够的内存,进行对象的保存,就会产生 OOM 异常 OutOfMemoryError。

如果出现 java.lang.OutOfMemoryError : Java heap space 异常,说明Java 虚拟机的堆内存不够,原因是:
1、Java 虚拟机的堆内存设置不够,可以通过参数 -Xms -Xmx 来调整
2、代码中创建了大量对象,且长时间不能被垃圾收集器收集(存在被引用),需要我们从代码的角度寻找问题

老年代:经历多次Minor  GC 依然存活的对象会进入老年代;连接池的对象一般会进入老年代,常驻内存的内存缓存一般也会进入老年代;

新生代到老年代的一般场景:

  • 1、普通情况下 通过设置该参数 XX:MaxTenuringThreshold
  • 2、分配的对象空间大于eden space。
  • 3、eden space剩余空间不足分配,且需要分配对象内存不小于eden space总空间的一半,直接分配到老年代,不触发Minor GC。适合-XX:+UseParallelGC、-XX:+UseParallelOldGC,即适合Parallel Scavenge。
  • 4、大对象直接进入老年代,使用-XX:PretenureSizeThreshold参数控制,适合-XX:+UseSerialGC、-XX:+UseParNewGC、-XX:+UseConcMarkSweepGC,即适合Serial和ParNew收集器。

永久区:永久存储区足一个常驻内存区域,用于存放JDK白身所携带的Class , Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾收器回收掉的,关闭JVM 才会释放此区域所占的内存。如果出现 java.lang.OutOfMemoryError: PermGen space ,说明是 Java 虚拟机的永久代 Perm 内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方 jar 包。例如:在一个Tomcat下部署很 多的应用或者大量动态反射生成的类不断被加载,最终导致Perml区被填满。
Jdkl.6及之前:有永久代,常量池在方法区
Jdkl.7:有永久代,但己经逐步“去水久代”,常量池在堆里
Jdkl.8 及之后:无永久代,常量池在元空间

二、堆参数调优

默认值:

参数设置:-Xms10M -Xmx10M -XX:+PrintGCDetails

JVM之堆的体系结构的更多相关文章

  1. 【JVM】堆体系结构及其内存调优

    堆体系结构 一个JVM实例只存在一个堆内存,堆内存的大小是可调节的.类加载器读取类文件后,需要把类.方法.常量.变量放在堆内存中,保存所有引用类型的真实信息,以方便执行器指向,堆内存分为三个部分:年轻 ...

  2. JVM的堆(heap)、栈(stack)和方法区(method)

    JVM主要由类加载器子系统.运行时数据区(内存空间).执行引擎以及与本地方法接口等组成.其中运行时数据区又由方法区Method Area.堆Heap.Java stack.PC寄存器.本地方法栈组成. ...

  3. [转]JVM内存堆布局图解分析

    JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C++语言执行的速度要慢 ...

  4. JVM内存堆布局图解分析

    JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C++语言执行的速度要慢 ...

  5. 五、JVM之堆内存

    堆结构分代图 堆结构分代的意义 Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代.老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略. 堆内存是虚拟机管理 ...

  6. JVM之堆参数

    1.Java 7和Java 8区别 Java 7堆结构 JDK 1.8之后将最初的永久代取消了,由元空间取代. 在Java8中,永久代已经被移除,被一个称为元空间的区域所取代.元空间的本质和永久代类似 ...

  7. JVM之堆体系结构

    1.Heap堆(Java7之前) 一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的.类加载器读取了类文件后,需要把类.方法.常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆 ...

  8. JVM的堆分配

    为了展示虚拟机如何使用方法区中的信息,下面来举例说明:   class Lava { private int speed = 5; void flow(){ } }     public class ...

  9. JVM中堆内存和栈内存的区别

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

随机推荐

  1. iptables [match] 常用封包匹配参数

    参数 -p, --protocol 范例 iptables -A INPUT -p tcp 说明 匹配通讯协议类型是否相符,可以使用 ! 运算符进行反向匹配,例如: -p !tcp 意思是指除 tcp ...

  2. vue+element-ui 字体自适应不同屏幕

    项目背景:屏幕自适应问题,当在不同分辨率的屏幕上显示页面时,页面的字体需要根据屏幕大小来自适应,想到使用rem作为字体的单位 vue-cli脚手架下的index.html中写入以下js脚本 <s ...

  3. spring boot The request was rejected because the URL was not normalized

    升级spring boot 1.5.10.RELEASE 版本后,突然发现之前能Nginx代理能请求的地址抛如下异常: org.springframework.security.web.firewal ...

  4. 高可用之keepalived的配置文件详解

    ! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover ...

  5. H3C ACL的标识

  6. 【codeforces 789B】Masha and geometric depression

    [题目链接]:http://codeforces.com/contest/789/problem/B [题意] 让你一个一个地写出等比数列的每一项 (注意是一个一个地写出); 有m个数字不能写; 且数 ...

  7. H5 网络状态接口

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 代码片段 修改Windows用户名

    cmd /c wmic useraccount where name=' 记录防备忘

  9. linux Do-it-yourself 探测

    探测也可以在驱动自身实现没有太大麻烦. 它是一个少有的驱动必须实现它自己的探测, 但是看它是如何工作的能够给出对这个过程的内部认识. 为此目的, short 模块进行 do- it-yourself ...

  10. Linux 内核 设备结构嵌入

    设备结构包含设备模型核心需要的来模型化系统的信息. 大部分子系统, 但是, 跟踪关于 它们驻留的设备的额外信息. 结果, 对设备很少由空设备结构所代表; 相反, 这个结构, 如同 kobject 结构 ...