JVM深入学习笔记四:JVM垃圾收集和内存分配

简介: <p>1. 垃圾判断算法</p> <p><span style="white-space:pre"></span>引用计数法,    给对象添加引用计数器,每有一个引用则+1, 没有则-1,为0为已死。python就是使用这种算法。  但是不能解决循环引用的问题。</p> <p><span style="white-space:pre"></span>根搜索算法。     从根开始向下

1. 垃圾判断算法

引用计数法,    给对象添加引用计数器,每有一个引用则+1, 没有则-1,为0为已死。python就是使用这种算法。  但是不能解决循环引用的问题。

根搜索算法。     从根开始向下搜索,如果有对象到根不可达则为死对象。 HopSpot使用的是这种算法。  

这里的根可以是栈中的引用对象, 方法区常量的引用对象,方法区静态属性的引用对象,JNI的引用对象。

两次标记。   虚拟机在回收对象时要做两次标记才会真的回收。无根的时候是一次,执行了finallise方法的时候会再标记一次。标记两次后,再执行到finalise方法就会回收对象。

回收方法区。 会回收常量池和做类卸载,可以使用-verbose:class来查看类的装载及卸载情况。

2. 垃圾收集算法

标记清除算法。 标记出所有需要回收的对象,标记完成后清除所有标记了的对象。   问题在于:效率不高,空间上会产生大量的碎片

复制算法。 把内存分为两个等块, 每次使用一块,当这一块满了之后把存活的对象转移到另外一块上去,然后清空这一块。  这样有点空间浪费。

HopSpot 的新生代基于这个算法,把内存分为了一个较大的Eden空间和两个较小的Survior空间。每次使用Eden和一个Survior,GC的时候把他们两个中存活的对象拷贝到另一个S空间,清空Eden和S1, 如果S2不够大,则会把对象复制到老生代。

标记整理                  当系统运行比较久后,对象的存活率比较高,复制算法就会有很多的复制操作,效率将会变低。因此对于老生代,使用标记-真理算法。

把存活对象标记并向一个方向清理,完成后把边界外的统一清空。

基于复制算法的新生代,标记整理的老生代,也就是分代收集的算法了。新生代GC(Minor GC), 老生代GC(Major GC)

3. 垃圾收集器

有很多种,主要是针对问题的不同,有单线程的,为了减少停顿时间的,还有使用不同算法实现的。 目前最新的叫做G1

4. 内存分配

优先在Eden上分配

参数:

-verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
-verbose:gc 打印GC的信息

-Xmn:新生代大小

-XX:Sur... : Eden和S的比

-XX:+Print.. : 打印详细的GC信息

代码:

public class MemoryAllocation {
	private static final int MB = 1024 * 1024;
	
	public static void main(String[] args) {
		byte[] allocation1 = new byte[2 * MB];
		byte[] allocation2 = new byte[2 * MB];
		byte[] allocation3 = new byte[2 * MB];
		byte[] allocation4 = new byte[4 * MB];
	}
}
输出:

<span style="color:#ff6666;">[GC [DefNew: 6487K->148K(9216K), 0.0037546 secs] 6487K->6292K(19456K), 0.0037798 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap</span>
 def new generation   total 9216K, used 4572K [0x35c10000, 0x36610000, 0x36610000)
<span style="color:#ff6666;">  eden space 8192K,  54% used [0x35c10000, 0x36061fa8, 0x36410000)
  from space 1024K,  14% used [0x36510000, 0x365352b8, 0x36610000)
  to   space 1024K,   0% used [0x36410000, 0x36410000, 0x36510000)</span>
 tenured generation   total 10240K, used 6144K [0x36610000, 0x37010000, 0x37010000)
 <span style="color:#ff6666;">  the space 10240K,  60% used [0x36610000, 0x36c10030, 0x36c10200, 0x37010000)</span>
 compacting perm gen  total 12288K, used 378K [0x37010000, 0x37c10000, 0x3b010000)
   the space 12288K,   3% used [0x37010000, 0x3706e8a0, 0x3706ea00, 0x37c10000)
    ro space 10240K,  54% used [0x3b010000, 0x3b58ee00, 0x3b58ee00, 0x3ba10000)
    rw space 12288K,  55% used [0x3ba10000, 0x3c0b2800, 0x3c0b2800, 0x3c610000)

大概的过程是,前三个对象分配在Eden上,当分配第四个的时候发现Eden不够大, 因此做GC,做GC的时候发现对象都比S大,因此分配到老生代去了。

最后将是Eden上对象4,  老生代上有1,2,3

大对象直接进入老生代

上面那个例子,加入参数-XX:PertenureSizeThreshold参数指定大于这个值的对象会直接进入老生代。


长期存活的对象将进入老生代

每熬过一次MinorGC年龄增加一岁,  -XX:MaxTenuringThreshold设置几岁的对象进入老生代。


大于平均值的进入老生代

当处于一个年龄的对象达到了数目的一半以上,那么比这个年龄大的将会进入到老生代。


相关文章
|
12月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
983 55
|
Arthas 监控 Java
Arthas memory(查看 JVM 内存信息)
Arthas memory(查看 JVM 内存信息)
982 6
|
7月前
|
存储 缓存 Java
我们来说一说 JVM 的内存模型
我是小假 期待与你的下一次相遇 ~
519 5
|
7月前
|
存储 缓存 算法
深入理解JVM《JVM内存区域详解 - 世界的基石》
Java代码从编译到执行需经javac编译为.class字节码,再由JVM加载运行。JVM内存分为线程私有(程序计数器、虚拟机栈、本地方法栈)和线程共享(堆、方法区)区域,其中堆是GC主战场,方法区在JDK 8+演变为使用本地内存的元空间,直接内存则用于提升NIO性能,但可能引发OOM。
|
存储 缓存 算法
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
725 29
JVM简介—1.Java内存区域
|
缓存 监控 算法
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略
|
监控 算法 Java
JVM—垃圾收集算法和HotSpot算法实现细节
JVM的垃圾收集算法和HotSpot的实现细节复杂但至关重要,通过理解和掌握这些算法,可以为Java应用程序选择合适的垃圾收集器,并进行有效的性能调优。选择适当的垃圾收集策略,结合合理的内存配置和日志分析,能够显著提升应用的运行效率和稳定性。
303 15
|
存储 算法 Java
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
231 6
|
存储 设计模式 监控
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
370 0
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
|
10月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
3140 0