jvm笔记

一.jvm内存模型

1.结构图

jvm笔记_第1张图片

2.详解

数据区:

1)方法区:也称"永久代",它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。

(JDK 1.7 和 1.8 将字符串常量由永久代转移到堆中)

2)  堆

程序中动态创建的所有对象都是存放在Java堆中的;

Java堆对所有的线程共享;

从分代GC的角度看,堆分为如下几个区:eden,s0,s1,tenured;

堆分区:

  1. 1.8以前JVM的内存模型:
    • 新生代(属于堆): 使用复制回收算法管理
      • eden: 堆中申请空间第一个考虑的位置;
      • s0(from):
      • s1(to):
    • 老年代(Old Generation, 属于堆)
    • 永久代(Survivor Space/Compacting Perm Generation, 属于方法区)
  2. 1.8内存模型
    • 新生代(New Generation,属于堆)
      • eden
      • s0(from)
      • s1(to)
    • 老年代(Tenured Generation,属于堆)
    • meta Space(元空间,属于方法区): 用来取代永久代,1.8之前的永久代的大小是固定的, 可能溢出, 而meta space的大小是动态扩容的;

指令区:

3)程序计数器: 指向当前线程正在执行的字节码指令的地址;

4)虚拟机栈:描述的是java方法执行的内存模型:每个方法被执行的时候都会创建一个"栈帧",用于存储局部变量表(包括参数)、操作栈、方法出口等信息。每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

5)本地方法栈:本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。

总结

名称 是否线程共享 特征 存储对象 配置
共享 分为新生代(eden+s0+s1)+老年代 存放对象实例 -Xms,-Xmx,-Xmm
方法区 共享

jdk1.7前为永久带

jdk1.8后为元空间

存储类加载信息,常量,静态遍历(1.7后字符串常量移到堆里面了)

-XX:permSize

XX:MaxpermSize

私有 分为虚拟机栈和本地方法栈 存放局部遍历表,操作栈,动态连接,方法出口 -XSs
程序计数器 私有 占用内存小 存放字节码行号

二,如何定位垃圾

1.引用计数,不采用,指的是维护对象被引用的次数,次数为0则意味着是垃圾。

2.根可达算法,指的是从GC Roots开始往下遍历所有引用的对象,(每个GC Root就是一个树状图),所有被引用到的对象就是需要存活的对象,其他对象可以被回收。GC Root指的是,虚拟机栈(栈帧中的本地变量表)中引用的对象,方法区中非基本类型的类静态变量(一个地址)所引用的对象,本地方法栈中JNI(即一般说的Native方法)引用的对象。

三.常见的垃圾回收算法

标记-清除:这是垃圾收集算法中最基础的,根据名字就可以知道,它的思想就是标记哪些要被回收的对象,然后统一回收。这种方法很简单,但是会有两个主要问题:

1.效率不高,标记和清除的效率都很低;

2.会产生大量不连续的内存碎片,导致以后程序在分配较大的对象时,由于没有充足的连续内存而提前触发一次GC动作。

复制算法:为了解决效率问题,复制算法将可用内存按容量划分为相等的两部分,然后每次只使用其中的一块,当一块内存用完时,就将还存活的对象复制到第二块内存上,然后一次性清除完第一块内存,再将第二块上的对象复制到第一块。但是这种方式,内存的代价太高,每次基本上都要浪费一半的内存。 于是将该算法进行了改进,内存区域不再是按照1:1去划分,而是将内存划分为8:1:1三部分,较大那份内存称为Eden区,其余是两块较小的内存区叫Survivor区。每次都会优先使用Eden区,若Eden区满,就将对象复制到第二块内存区上,然后清除Eden区,如果此时存活的对象太多,以至于Survivor不够时,会将这些对象通过分配担保机制复制到老年代中。

标记-整理:该算法主要是为了解决标记-清除,产生大量内存碎片的问题;当对象存活率较高时,也解决了复制算法的效率问题。它的不同之处就是在清除对象的时候现将可回收对象移动到一端,然后清除掉端边界以外的对象,这样就不会产生内存碎片了。

分代收集:现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理 或者 标记-清除。

 

四.JVM分代模型

1.. 新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace
   1. 永久代 元数据 - Class
   2. 永久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存)
   3. 字符串常量 1.7 - 永久代,1.8 - 堆
   4. MethodArea(方法区)逻辑概念 - 永久代、元空间
   
3. 新生代 = Eden + 2个suvivor区 (使用复制算法)
   1. YGC回收之后,大多数的对象会被回收,活着的进入s0
   2. 再次YGC,活着的对象eden + s0 -> s1
   3. 再次YGC,eden + s1 -> s0
   4. 年龄足够 -> 老年代 (15 CMS 6)
   5. s区装不下 -> 老年代
   
4. 老年代 (标记清除或者标记整理算法)
   1. 顽固分子
   2. 老年代满了FGC Full GC
   
5. GC Tuning (Generation)
   1. 尽量减少FGC
   2. MinorGC = YGC
   3. MajorGC = FGC

 

你可能感兴趣的:(【JAVASE】)