I.JVM进程的生命周期

  1. JVM实例的生命周期和java程序的生命周期保持一致,即一个新的程序启动则产生一个新的JVM进程实例,程序结束则JVM进程实例伴随着消失。那么程序启动和程序终止就是JVM实例生命周期的两个边界,两个边界点可以这么理解:一个拥有程序入口(main函数)的class在执行main方法时,相应的JVM就被创建了(即JVM生命周期的起点),当由此main函数启动的所有非守护线程都终止时,JVM即退出(JVM实例生命周期的终点)。举个实例来描述一下JVM实例的生命周期:

    (1) JVMInstance.java

    public class JVMInstance {public static void main(String[] args) {System.out.println("hello world!");}
    }
    

    (2) javac JVMInstance.java 编译源码生成class文件 
    (3) java JVMInstance 
    在用java 命令执行编译好的字节码文件时,java命令会调用java launcher来创建JVM实例,而java.exe的源代码在jdk/src/share/bin/java.c定义(可以在openJDK中看到其中的源代码)。 java.c中主要包含了两个主要的函数:

    int main(int argc, char ** argv); int JNICALLJavaMain(void * _args); 其中主要完成的功能是新建JVM实例进程,实例化一些守护线程,包括监视器线程(WatcherThread),编译器线程(Compiler Thread),GC线程(GC Thread)。(具体源代码可以细扣一下,有现成的研究大家也分享一下) //TODO ps:学习一下java.c 源代码

II.JVM内存模型

在内存结构上每个JVM实例都有自己的一套内存模型(即:堆,方法区,方法栈,本地方法栈,程序技术器),当JVM实例创建时内存模型也随之创建,没猜错的话java.c的这段代码就是用来分配JVM实例内存的:

{int i;original_argv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1));for(i = 0; i < argc+1; i++) {
original_argv[i] = argv[i];}
}CreateExecutionEnvironment(&argc, &argv,jrepath, sizeof(jrepath),jvmpath, sizeof(jvmpath),original_argv);
...

JVM实例的内存模型结构入下图(参考《深入理解java虚拟机》):  上图中标出了红框和绿框,其中红框代表在一个JVM进程实例内所有线程共享的内存模型区域,绿框表示线程内存数据隔离的区域,即方法区和堆中的数据JVM进程内线程共享,栈和程序计数器每个线程有自己的一套。(看过一些博客把方法区也画入了堆内存结构中,感觉不是很合理,虽然java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-heap(非堆))。方法区主要存储:类加载的信息,常量,静态变量,即时编译器编译后的代码等数据。堆内存又分为 Yong、Tenured、Perm。虚拟机栈是执行普通方法是需要用的,本地方法栈就是执行本地方法栈的时候用的。程序计数器就是辅助程序执行用的,记录程序指令指针。 JVM执行引擎是JVM实例进程中的一个线程,用来执行字节码指令的。

III.JVM内存垃圾回收机制及常用垃圾回收器

(1)分代回收:在运行的程序中,会创建大量端生命周期的对象和小部分长生命周期的对象。对于短生命周期对象,垃圾回收线程就需要频繁的检测释放,对于长周期的对象垃圾回收检测线程探测频率就可以少一点。为了满足这种需求SUN的JVM内存是分代管理,分代回收的(说白了分代管理就是为了分代回收,哪天如果不需要分代回收了,那分代管理机制也就不需要了,我个人觉得哈)。

(2)常用的垃圾回收算法:

标记清除算法: 概述:回收过程分两个阶段,即先“标记” 再 “清除”,首先GC线程根据根搜索算法以及回收判定策略,判断对象是否需要被回收,将需要被回收的对象全都标记出来,然后统一回收掉。这种算法是比较基础的算法,后续的算法基本是基于这种算法的。 主要缺点:一个是效率问题,标记和清除过程效率都不高;另外一个是空间问题,标记清除之后会产生不连续的内存碎片(如果空间碎片太多,当分配一个大对象的时候,因为找不到一块合适的内存区域,就会提前出发一次GC操作)。

复制算法: 复制算法基本思想就是,将内存分成大小相等的两块,每次只使用其中的一块。当其中一块内存用完了,就将活着的对象按序摆放到另外一块内存中,然后将另一块内存清理掉。 优缺点:优点就是与标记清除算法相比,效率明显提高了,并且不会产生内存碎片。缺点也是显而易见就是内存需求更大了,每次都需要有一块内存闲置。(ps:现在的商业虚拟机都采用这种收集算法回收新生代,例如:SUN JDK1.3.1版本启用的HotSpot虚拟机)

标记整理算法: 标记整理算法主要分为算个阶段,首先将要清理的对象标记出来和标记清除的第一阶段一样,然后将有效的对象向一端移动(类似于我们有win7优化到时整理内存碎片的效果),最后将有效对象边界以外的对象全部回收掉。 优缺点:有点就是和标记清除算法相比减少了内存碎片,和复制算法相比提高内存利用率。 缺点:效率较低。

(3)常用的垃圾收集器:

  1. Serial收集器:单线程收集器,只会启动一条线程进行内存回收工作,在回收的过程中,必须暂停其他所有的工作线程。serial是一个比较原始的收集器,运行在Server端的JVM已经不再使用Serial,不过对于运行在Client端的JVM是一个很好的选择(单线程嘛,意味着没有线程切换开销)。Serial对于Yong区采用的是复制算法,对于Tenured采用的是标记整理算法。
  2. ParNew收集器: ParNew收集器是Serial收集器的多线程版本,对于收集算法以及控制参数Serial和ParNew一样,ParNew是运行在Server模式下的JVM的首选的新生代收集器,主要原因是除了ParNew能和Serial配合使用外,只有ParNew能和CMS协同工作。
  3. Parallel Scavenge收集器:多线程的新生代收集器,采用的复制算法,看上去和ParNew一样,但专注点不同,ParNew专注于在收集过程中缩短用户线程的停顿时间,而它专注于达到一个可控的吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间))。
  4. Serial Old收集器:Serial的老年代版本,采用的是标记整理算法,现在跑Server端JVM进程实例不经常使用的收集器,比较古老。
  5. Parallel Old收集器:Parallel Scavenge的老年代版本,使用多线程和标记-整理算法。Paralle Old出现之后就可以和Parallel Scavenge配合使用了。
  6. CMS收集器:CMS(Concurrent Mark Sweep)收集器是一种以获取最短停顿时间为目标的收集器,目前在市场上使用的占比很大。它是一款老年代收集器,采用的是标记-清除算法。它在清理过程中主要包含4个阶段,分别是初始标记,并发标记,重新标记,并发清除。其中只有初始标记和重新标记需要停顿用户线程,在并发标记和并发清除阶段,用户线程和回收器线程可以共同运行(将整个回收过程分成好多段,以达到减少停顿用户线程的目的)。
  7. G1收集器是JDK1.7提供的收集器,G1基于标记-整理算法(没有内存碎片),试用于新生代和老年代。它改变了收集的策略,不在针对新生代和老年代整个区域进行收集,而是把新生代或老年代划分成多个单元格,针对每个单元格的使用程度,对每个单元格进行收集,属于算法的优化和突破。

下面这个图不错的表达了各个收集器使用的分代区域: 

IV.JVM垃圾回收日志结构分析及常用的命令

我们在我们Server的gc log上经常看到下面的这个日志。 总结一下各个字段表达的是什么意思: Young GC: 

Full GC: 

JVM内存管理学习总结(一)相关推荐

  1. 详解JVM内存管理与垃圾回收机制2 - 何为垃圾

    随着编程语言的发展,GC的功能不断增强,性能也不断提高,作为语言背后的无名英雄,GC离我们的工作似乎越来越远.作为Java程序员,对这一点也许会有更深的体会,我们不需要了解太多与GC相关的知识,就能很 ...

  2. 详解JVM内存管理与垃圾回收机制5 - Java中的4种引用类型

    在Java语言中,除了基础数据类型的变量以外,其他的都是引用类型,指向各种不同的对象.在前文我们也已经知道,Java中的引用可以是认为对指针的封装,这个指针中存储的值代表的是另外一块内存的起始地址(对 ...

  3. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  4. JVM内存管理:深入Java内存区域与OOM

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝 ...

  5. JVM内存管理及GC机制

    转载自:http://blog.csdn.net/suifeng3051/article/details/48292193 一.概述 Java GC(Garbage Collection,垃圾收集,垃 ...

  6. 形式参数内存在哪java_深入浅出Java中JVM内存管理

    原标题:深入浅出Java中JVM内存管理 Java岗位面试,JVM是对程序员基本功考察,通常会问你对JVM了解吗?可以分几部分回答这个问题,首先JVM内存划分 | JVM垃圾回收的含义 | 有哪些GC ...

  7. 【JVM调优】JVM内存管理调优浅谈

    什么是JVM Java Virtual Machine,Java虚拟机 Java虚拟机有自己完善的硬件架构,如处理器.堆栈等,还具有相应的指令系统. Java虚拟机本质上就是一个程序,当它在命令行上启 ...

  8. Windows内存管理学习笔记(三)—— 无处不在的缺页异常

    Windows内存管理学习笔记(三)-- 无处不在的缺页异常 缺页异常 实验一:设置虚拟内存 无处不在的缺页 位于页面文件 保留与提交的误区 实验二:理解缺页异常 EXECUTE_WRITECOPY ...

  9. Windows内存管理学习笔记(二)—— 物理内存的管理

    Windows内存管理学习笔记(二)-- 物理内存的管理 物理内存 实验一:理解MmNumberOfPhysicalPages MmPfnDatabase _MMPFN 物理页状态 六个链表 实验二: ...

最新文章

  1. 【论文速读】RandLA-Net大规模点云的高效语义分割
  2. 云炬金融每日一题20211012
  3. 《犯罪心理学》读书笔记(part11)--犯罪心理的性别差异(中)
  4. 【数据结构与算法】快排、归并 O(nlogn) 基于比较
  5. gatewayproperties 是空_杨丞琳演唱会踩空,从二楼高台掉到一楼,手脚擦伤,引发网友热议...
  6. 如何将文件二进制传输至aix服务器,有什么办法把文件从WINDOWS系统中传到AIX中?...
  7. td外边加div为啥不隐藏_过年炸油饼注意了,秘制配方比例教给你,柔软不吸油,放凉了不硬...
  8. just show up失败让我们成长
  9. 如何查看微信页面的源代码
  10. 【网管知识】狼牙抓鸡器中毒后的解决办法
  11. 百度,高德地图经纬度转换
  12. MTK6589平板上launcher的一些小修改
  13. java接口文档怎么写_如何写好API接口文档
  14. 使用Aspose给PDF加密,免受未经授权的访问和内容篡改
  15. 华为云mysql教程_华为云+NextCloud(私人云盘搭建)
  16. Path.Direction.CCW与Path.Direction.CW的意思
  17. 计算机中的取余 ( % )
  18. 京沪高铁上火车位置的实时监视模拟网站的开发
  19. 用python抢火车票
  20. 深析超市商品管理系统设计

热门文章

  1. Swift 中的内存管理详解
  2. rabbitmq可靠发送的自动重试机制 --转
  3. 如何用Python画一棵漂亮的树
  4. 软工实践原型设计——PaperRepositories
  5. 多人开发情况下的字符串本地化
  6. React+Redux+中间件
  7. 026——VUE中事件修饰符之使用$event与$prevent修饰符操作表单
  8. 联想架构调整:智能手机业务很重要
  9. ubuntu 目录结构
  10. 《CLR Via C# 第3版》笔记之(十四) - 泛型高级