jvm 内存模型及垃圾回收过程

1.jvm 内存模型

pc寄存器:行号指示器,字节码解释器工作时就是通过改变这个计数器的值,来选下一条字节码指令,比如分支,循环,跳转,异常 处理,线程恢复等基础功能靠这个计数器来完成。ps:由于java的多线程是线程轮流切换的,一个处理器同一时刻只会执行一条线 程 (用来记录代码执行到哪里)

虚拟机栈:一个线程执行会有至少一个方法,没当线程进入一个方法,会在虚拟机栈创建一个栈帧,用于存储局部变量表(基本7种数据类型,对象引用)、操作帧,方法出 口等信息。每一个方法被调用即入栈,完成即出栈 ,

                 局部变量放在虚拟机栈

本地方法栈:

  • 本地方法栈(Native Method Stacks)与 Java 虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的 Native 方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。
  • Navtive 方法是 Java 通过 JNI 直接调用本地 C/C++ 库,可以认为是 Native 方法相当于 C/C++ 暴露给 Java 的一个接口,Java 通过调用这个接口从而调用到 C/C++ 方法。当线程调用 Java 方法时,虚拟机会创建一个栈帧并压入 Java 虚拟机栈。然而当它调用的是 native 方法时,虚拟机会保持 Java 虚拟机栈不变,也不会向 Java 虚拟机栈中压入新的栈帧,虚拟机只是简单地动态连接并直接调用指定的 native 方法。


 

方法区:存放编译代码类 

               静态变量

               常量

堆:jdk 1.8 以后分为年轻代和老年代  ,jdk 1.8以前是永久代

     1.字符串存在永久代中,容易出现性能问题和永久代内存溢出

     2.永久代会为 GC 带来不必要的复杂度,并且回收效率偏低

     3.永久代内存大小不太容易设置

      

       new 出来的对象一开始存放在年轻代 

      年轻代:Egen  so  s1  

       

2.对象在jvm 中的分布

       

3.jvm 垃圾回收过程

   回收的是堆内存

JVM 参数配置 java -jar -Xmx10m  -Xms10m -Xmn5m -XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=10M -XX:SurvivorRatio=8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC

参数含义 Xmx:             分配的最大堆内存

Xms:            分配的最小堆内存

Xmn:            年轻代大小

XX:MetaspaceSize:     元数据空间大小   (1.7 memaryspacesize)

MaxMetaspaceSize:    最大元数据空间

SurvivorRatio:        年轻代与存活代大小配比

UseParNewGC:        年轻代垃圾回收算法

UseConcMarkSweepGC:    老年代垃圾回收算法

由于GC开始垃圾回收时会挂起应用线程,严重影响了性能,调优的目是为了尽量降低GC所导致的应用线程暂停时间、 减少Full GC次数

Xms、 -Xmx 通常设置为相同的值,避免运行时要不断扩展JVM内存,这个值决定了JVM heap所能使用的最大内存。

-Xmn 决定了新生代空间的大小,新生代Eden、S0、S1三个区域的比率可以通过-XX:SurvivorRatio来控制(假如值为 4  表示:Eden:S0:S1 = 4:3:3 )

-XX:MaxTenuringThreshold 控制对象在经过多少次minor GC之后进入老年代,此参数只有在Serial 串行GC时有效。

-XX:PermSize、-XX:MaxPermSize 用来控制方法区的大小,通常设置为相同的值。

1.避免新生代大小设置过小 ===========》频繁minor GC。 影响新能

2、避免新生代设置过大===============》执行回收时间长。

举个例子,过小: 家里买了个垃圾桶 ,太小, 经常容易满, 就要打, 很浪费时间哦;过大:发现垃圾变臭了, 扔垃圾的时候感觉很吃力, 这两种都需要避免;

1. 一般创建对象都是在各种方法里执行的,一旦方法运行完毕,方法局部变量引用的那些对象就会成为Eden区里的垃圾对象,可以被回收

2. 接着随着Eden区不断的创建对象,就会逐步的塞满,当然这个时候可能塞 满Eden区的对象里大多数都是垃圾对象。一旦Eden区塞满之后,就会触发一次 Young GC 

3.Young GC 采用复制算法,把存活的对象放入S0,然后垃圾回收器直接回收掉 Eden区域里剩余的垃圾对象

下一次eden 满了之后,触发第二次Young GC  so 的对象放在s1  ,s0和s1只会使用一种,便于垃圾回收的复杂度

4. 下一次如果Eden区满了,就会再次触发Young GC,把Eden区和S0区里的存活对象转移到S1区里去,然后直接清空掉Eden区和S0区中的垃圾对象

5. 系统运行一段时间之后,Eden区再次满了,这次发生了点意外,Eden存活的对象占用的空间大于S0的总空间,这时这部分对象就会进入老年代。

6.一旦老年代对象过多,就可能会触发Full GC,Full GC必然会带着Old GC,也就是针对老年代的GC,而且一般会跟着一次Young GC  

对象进入老年代的情况:

1 一个对象在年轻代里躲过15次垃圾回收,年龄太大了,寿终正寝,进入老年代,可以使用参数控制 -XX:MaxTenuringThreshold 2 对象太大了,超过了一定的阈值,直接进入老年代,不走年轻代,可以使用参数控制 -XX:PretenureSizeThreshold

3 YoungGC过后存活对象太多了,导致Survivor区域放不下了,这批对象会进入老年代

4 动态年龄判断。可能几次Young GC过后,Surviovr区域中的对象占用了超过50%的内存,此时会判断如果年龄1+年龄2+年龄N的对象总和超过了Survivor区域的50%,此时年龄N以及之上的对象都进入老年代,这是动态年龄判定规则

Full Gc 的情况:

1 老年代自身可以设置一个阈值,使用参数-XX:CMSInitiatingOccupancyFraction控制,一旦老年代内存使用达到这个阈值,就会触发Full GC,一般建议调节大一些  

2 在执行Young GC之前,如果判断发现老年代可用空间小于了历次Young GC后升入老年代的平均对象大小的话,那么就会在Young GC之前触发Full GC,先回收掉老年代一批对象,然后再执行Young GC。

 3 如果Young GC过后的存活对象太多,Survivor区域放不下,就要放入老年代,要是此时老年代也放不下,就会触发Full GC,回收老年代一批对象,再把这些年轻代的存活对象放入老年代中

降低young gc  的频率  ,尽量避免full gc   

查看gc情况:

1.查看java 进程   jps -l

2.jstat -gcutil pid 时间间隔 次数 dump 文件: jmap  -dump:[live], format=b, file=filename

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JVM内存模型分为以下几个区域: 1. 程序计数器:用于记录当前线程执行的字节码位置,是线程私有的。 2. Java虚拟机栈:用于存储每个方法的局部变量、操作数栈、动态链接、方法出口等信息,是线程私有的。 3. 本地方法栈:与虚拟机栈类似,用于存储本地方法的信息,是线程私有的。 4. Java堆:用于存储对象实例和数组,是所有线程共享的内存区域。Java堆分为新生代和老年代,新生代又分为Eden区、Survivor区1和Survivor区2。 5. 方法区:用于存储类的信息、常量、静态变量等数据,是所有线程共享的内存区域。 垃圾回收JVM自动管理内存的重要机制。垃圾回收可以清理无用的对象,释放内存空间,防止内存泄漏和OOM等问题。JVM垃圾回收主要有以下几种算法: 1. 标记-清除算法:首先标记出所有需要回收的对象,然后清除这些对象所占用的内存空间。这种算法容易产生内存碎片,影响空间利用率。 2. 复制算法:将可用内存空间分为两部分,每次只使用其中一部分。当这部分空间用完后,将所有存活的对象复制到另一部分空间中,然后清除原空间中所有对象。这种算法效率高,但空间利用率不高。 3. 标记-整理算法:先标记出所有需要回收的对象,然后将所有存活的对象向一端移动,然后清除边界外的所有对象。这种算法可以解决内存碎片问题,但效率比较低。 4. 分代收集算法:根据对象年龄的不同将Java堆分为不同的区域,每个区域采用不同的垃圾回收算法。新生代采用复制算法,老年代采用标记-整理算法或标记-清除算法。 JVM垃圾回收机制是自动的,但我们可以通过调整JVM的参数来影响垃圾回收的效率和行为。例如,可以通过-Xmx参数来设置Java堆的最大大小,可以通过-XX:+UseSerialGC参数来指定垃圾回收算法为串行收集器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值