JVM内存管理
2019-02-15 15:59:06 0 举报
AI智能生成
JVM内存管理分享
作者其他创作
大纲/内容
JVM内存管理
物理内存与虚拟内存
物理内存即RAM(随机存储器)
寄存器,用于存储计算单元执行指令(如浮点,整数等运算)
地址总线,连接处理器和RAM
虚拟内存使得多个进程在同时运行时可以共享物理内存
内核空间与用户空间
内核空间指操作系统运行时所使用的用于程序调度,虚拟内存的使用或连接硬件资源等的程序逻辑
用户空间指用户运行程序所占用的内存空间
Java中需要使用内存的组件
java堆
用于存储Java对象的内存区域
-Xmx表示堆的最大大小
-Xms表示堆的初识大小
一旦分配完成,就不能在内存不够时再向操作系统重新申请
线程
每个线程创建时JVM会为线程创建一个堆栈,通常在256KB~756KB之间
类和类加载器
在Sun SDK中被存储在堆中,这个区域叫永久代(PermGen区)
只有 HotSpot 才有 PermGen space
JRockit(Oracle)、J9(IBM) 并没有PermGen space
JDK1.8中 PermSize 和 MaxPermGen 已经无效,JDK1.8使用元空间替代PermGen空间,元空间并不在虚拟机中,而是使用本地内存
默认的3个类加载器
Bootstrap ClassLoader
ExtClassLoader
AppClassLoader
NIO
jdk1.4版本之后引入了一种基于通道和缓冲区来执行I/O的新方式
使用java.nio.ByteBuffer.allocateDirect()方法分配内存,分配的是本机内存而不是Java堆内存
每次分配内存时会调用操作系统的os::malloc()函数
JNI
JNI使得本机代码(如C语言程序)可以调用Java方法,也就是native memory
JVM内存结构
PC寄存器
记录线程当前执行到哪条指令
栈
堆
方法区
用于存储类结构信息,可以被所有线程共享,它不会频繁的GC
运行时常量池
代表运行时每个class文件中的常量表
1.数字常量
2.方法
3.字段的引用
本地方法栈
为JVM运行Native方法准备的空间
JVM内存回收策略
回收原则
引用计数法
给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1;当引用失效时,计数器值-1。这种算法使用场景很多,但是,Java中却没有使用这种算法,因为这种算法很难解决对象之间相互引用的情况
可达性分析法
通过一系列称为“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链(即GC Roots到对象不可达)时,则证明此对象是不可用的
引用状态
强引用
代码中普遍存在的类似\"Object obj = new Object()\"这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象
软引用
描述有些还有用但并非必需的对象。在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。Java中的类SoftReference表示软引用
弱引用
描述非必需对象。被弱引用关联的对象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。Java中的类WeakReference表示弱引用
虚引用
这个引用存在的唯一目的就是在这个对象被收集器回收时收到一个系统通知,被虚引用关联的对象,和其生存时间完全没关系。Java中的类PhantomReference表示虚引用
方法区的垃圾回收
废弃常量
以字面量回收为例,如果一个字符串“abc”已经进入常量池,但是当前系统没有任何一个String对象引用了叫做“abc”的字面量,那么,如果发生垃圾回收并且有必要时,“abc”就会被系统移出常量池
无用的类
该类的所有实例都已经被回收,即Java堆中不存在该类的任何实例
加载该类的ClassLoader已经被回收
该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
垃圾收集算法
标记-清除(Mark-Sweep)算法
分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象
复制(Copying)算法
它将可用的内存分为两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉
标记-整理(Mark-Compact)算法
让所有存活对象都向一端移动,然后直接清理掉边界以外的内存
分代收集算法
大批对象死去、少量对象存活的(新生代),使用复制算法,复制成本低;对象存活率高、没有额外空间进行分配担保的(老年代),采用标记-清理算法或者标记-整理算法
垃圾收集器
G1收集器(支持收集新生代和老年代)
并行和并发。使用多个CPU来缩短Stop The World停顿时间,与用户线程并发执行
分代收集。独立管理整个堆,但是能够采用不同的方式去处理新创建对象和已经存活了一段时间、熬过多次GC的旧对象,以获取更好的收集效果
空间整合。基于标记 - 整理算法,无内存碎片产生
可预测的停顿。能简历可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒
Young Generation
Serial收集器(jdk1.3)
采用复制算法的单线程的收集器
ParNew收集器(jdk1.4)
ParNew收集器其实就是Serial收集器的多线程版本
Parallel Scavenge收集器(jdk1.4)
Parallel Scavenge收集器也是一个新生代收集器,也是用复制算法的收集器,也是并行的多线程收集器
Parallel Scavenge收集器是虚拟机运行在Server模式下的默认垃圾收集器
Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量
Tenured Generation
Parallel Old收集器(jdk1.6)
Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法
CMS收集器(jdk1.5)
CMS(Conrrurent Mark Sweep)收集器是以获取最短回收停顿时间为目标的收集器。使用标记 - 清除算法
1.初始标记,标记GCRoots能直接关联到的对象,时间很短
2.并发标记,进行GCRoots Tracing(可达性分析)过程,时间很长
3.重新标记,修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,时间较长
4.并发清除,回收内存空间,时间很长
Serial Old收集器(jdk1.5)
Serial收集器的老年代版本,同样是一个单线程收集器,使用“标记-整理算法”
GC
Minor GC
从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC
当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了。所以分配率越高,越频繁执行 Minor GC
内存池被填满的时候,其中的内容全部会被复制,指针会从0开始跟踪空闲内存
执行 Minor GC 操作时,不会影响到永久代
质疑常规的认知,所有的 Minor GC 都会触发“全世界的暂停(stop-the-world)”,停止应用程序的线程
Major GC
Major GC 是清理老年代
Full GC
Full GC 是清理整个堆空间—包括年轻代和老年代
JVM参数
-Xmx3550m
设置堆最大值
-Xms3550m
设置初始堆大小
-Xss128k
设置线程栈大小
-Xmn2g
设置年轻代大小,在整个堆内存大小确定的情况下,增大年轻代将会减小年老代,反之亦然
-XX:NewSize=1024m
设置年轻代初始值
-XX:MaxNewSize=1024m
设置年轻代最大值
-XX:PermSize=256m
设置持久代初始值
-XX:MaxPermSize=256m
设置持久代最大值
-XX:NewRatio=4
设置年轻代(包括一个Eden区和两个Suvivor区)和年老代的比值
-XX:SurvivorRatio=4
设置Suvivor区和Eden区的比值
-XX:MaxTenuringThreshold=7
表示一个对象如果在Survivor区(救助空间)移动了7次还没有被垃圾回收就进入年老代
0 条评论
回复 删除
下一页