C语言申请内存:malloc free
C++: new delete
Java: new ?
自动内存回收,编程上简单,系统不容易出错,手动释放内存,容易出两种类型的问题:
忘记回收多次回收 垃圾指没有任何引用指向的一个对象或者多个对象(循环引用,垃圾堆)。 java的调优机制就集中在垃圾回收器的选择和参数设置上。标记清除(mark-sweep) - 位置不连续 产生碎片(两遍扫描)
拷贝算法(copying) - 没有碎片,浪费空间
标记压缩(mark-compact) - 没有碎片,效率偏低(两遍扫描,内存移动需要线程同步,影响效率)
部分垃圾回收器使用的模型
新生代 + 老年代 + 永久代(1.7)/ 元数据区(1.8) Metaspace
永久代 元数据 - Class永久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存,由操作系统管理)字符串常量 1.7 - 永久代,1.8 - 堆MethodArea逻辑概念 - 永久代、元数据新生代 = Eden + 2个suvivor区
YGC回收之后,大多数的对象会被回收,活着的进入s0再次YGC,活着的对象eden + s0 -> s1再次YGC,eden + s1 -> s0年龄足够 -> 老年代 (15 CMS 6)s区装不下 -> 老年代老年代
顽固分子老年代满了FGC Full GC(包括新生代和老年代全部gc一次)GC Tuning调优 (Generation 针对于分代模型)
尽量减少FGC(效率很底,可能会系统停顿)MinorGC = YGCMajorGC = FGCjvm的内存模型归gc回收器模型管
Serial (stw:stop the world)年轻代 串行回收(小孩子扔线团和妈妈清理的场景。)
PS 年轻代 并行回收(小孩子扔线团和长辈一起清理的场景。)
ParNew 年轻代 配合CMS的并行回收(约等于PS,可以配合CMS用)
SerialOld
ParallelOld
ConcurrentMarkSweep (CMS)老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(降低至200ms以内)
G1(10ms)(jdk1.9以上默认)
ZGC (1ms) PK C++
Shenandoah
Eplison(jdk11新加,不回收垃圾,jvm调试用)
jvm1.8默认的垃圾回收:PS + ParallelOld
垃圾回收器的演进与内存的大小发展有关系,内存越大与回收线程越多并不呈线性正相关,因为CPU性能(瓶颈)受限于线程切换(contextSwitch),影响gc清理。
因此诞生了CMS(缺点:内存碎片化,浮动垃圾,此时若有大对象进来,调用serial old来清理腾地方,卡顿时间很久),jdk第一个并发执行的垃圾回收器,CMS的4个阶段:
初始标记:标记根对象(STW)并发标记(mark sweep):并行;存在标记的重复利用(错标,严重),不用的没标记的问题(漏标,浮动垃圾)重新标记(STW),修改错标,又重新扫描一遍。并发清理。 怎么标记?怎么修改?并发标记算法(三色标记算法)错标cms的解决方案:A产生新的引用,重新变灰G1的产生
告别物理分代,进行逻辑分代,分而治之。
G1处理java文件的运行效率比其他的垃圾回收器的效率慢3%-4%(问题不大),因为存在**屏障(新建对象的时候),用于垃圾回收的标记。
转:深入理解Java G1垃圾收集器
JVM的命令行参数参考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
JVM参数分类
标准: - 开头,所有的HotSpot都支持
非标准:-X 开头,特定版本HotSpot支持特定命令
不稳定:-XX 开头,下个版本可能取消
-XX:+PrintCommandLineFlags
-XX:+PrintFlagsFinal 最终参数值
-XX:+PrintFlagsInitial 默认参数值