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设置几岁的对象进入老生代。


大于平均值的进入老生代

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


相关文章
|
14天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
12天前
|
Java Linux Windows
JVM内存
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制。
11 1
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
68 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
23天前
|
算法 Java
垃圾收集对内存碎片有什么影响?
垃圾收集对内存碎片有什么影响?
|
1月前
|
存储 算法 Java
聊聊jvm的内存结构, 以及各种结构的作用
【10月更文挑战第27天】JVM(Java虚拟机)的内存结构主要包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和运行时常量池。各部分协同工作,为Java程序提供高效稳定的内存管理和运行环境,确保程序的正常执行、数据存储和资源利用。
50 10
|
30天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
1月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
51 2
|
22天前
|
算法 Java
不同垃圾收集器对内存碎片的处理
不同垃圾收集器对内存碎片的处理
|
30天前
|
监控 安全 Java
Java Z 垃圾收集器如何彻底改变内存管理
大家好,我是V哥。今天聊聊Java的ZGC(Z Garbage Collector)。ZGC是一个低延迟垃圾收集器,专为大内存应用场景设计。其核心优势包括:极低的暂停时间(通常低于10毫秒)、支持TB级内存、使用着色指针实现高效对象管理、并发压缩和去碎片化、不分代的内存管理。适用于实时数据分析、高性能服务器和在线交易系统等场景,能显著提升应用的性能和稳定性。如何启用?只需在JVM启动参数中加入`-XX:+UseZGC`即可。
145 0
|
1月前
|
存储 Kubernetes 架构师
阿里面试:JVM 锁内存 是怎么变化的? JVM 锁的膨胀过程 ?
尼恩,一位经验丰富的40岁老架构师,通过其读者交流群分享了一系列关于JVM锁的深度解析,包括偏向锁、轻量级锁、自旋锁和重量级锁的概念、内存结构变化及锁膨胀流程。这些内容不仅帮助群内的小伙伴们顺利通过了多家一线互联网企业的面试,还整理成了《尼恩Java面试宝典》等技术资料,助力更多开发者提升技术水平,实现职业逆袭。尼恩强调,掌握这些核心知识点不仅能提高面试成功率,还能在实际工作中更好地应对高并发场景下的性能优化问题。