• 架构图

  • 基本概念说明

    • 堆(heap):数据存储,对象实例;空间往上增长,线程共享区;大小可通过-Xmx和-Xms配置

      • 新生代(Young Generation):划分为Eden Space和两个Survivor(From Space 和To Space),new object首先存放在Eden区,Eden空间不足,进行GC,将存活的对象放到From Space;如果From Space已满,再进行GC,将存活的对象放到To Space;如果To Space已满,则再次GC,将存活的对象放入旧生代(Old Generation);可用-XX:survivorRatio控制Eden和Survivor的比例(默认值为8,即Eden占8/10, 另两个survivor各占1/10),或-Xmn配置新生代;-XX:NewSize和-XX:MaxNewSize分别代表新生代的初始值和最大值;
      • 旧生代(Old Generation):存放新生代经过三次垃圾会后仍存活的对象,如果旧生代已满,进行FullGCC,如果FullGCC后仍然无法存储对象,则报OutOfMemoryError(原因:要么heap设置大小不够;要么应用创建太多对象,且由于被引用而长时间不能被回收);
      • 持久代(Permanent Generation):存放类的元数据(方法、字段、类和包上描述数据,如注解Annotation,注释等,元数据可用于创建文档,跟踪代码中的依赖性如重构或重载,执行编译时检查,代码分析)、常量池、静态变量;如果出现OutOfMemoryError: PermGen space,原因有二:加载jar太多;或大量动态反射的类生成;可通过-XX:PermSize和-XX:MaxPermSize配置初始值和最大值;JDK1.8后将元数据移植到本地内存(好处:如多个项目的共享jar在本地内存只有一份),HotSopt VM为其分配或释放内存;可通过-XX:MetaspaceSize 和 -XX:MaxMetaspaceSize配置大小;
      • JDK1.8后将元数据存放在Metaspace区域(本地内存,取代method area区域),常量池和静态变量仍在Heap的持久代中;

    • 栈(stack):程序执行,处理数据;空间动态增长(对象可垃圾回收),一个线程对应一个栈,每个方法对应一个frame,其中存储局部变量(局部变量区),方法返回值和程序运行产生的中间值(操作数栈)。基本类型长度固定(不会动态增长),需要空间较小,存放栈中;也存放对象引用;Object ob = new Object()一个最基本的对象,占用空间:占的空间为:4byte(栈)+8byte(堆);如Class A{

          int i;
          boolean b;
          Object obj;
      },其大小为:A(8byte)+int(4byte)+boolean(1byte)+引用(4byte)=17byte,但分配时为8的倍数,所以空间为24byte。
    • PC Register:存储了下一条将要执行的指令;
    • class load 机制

      • Custom ClassLoader: 应用程序自定义的ClassLoader, 如Tomcat会根据J2EE规范自行实现ClassLoader加载过程中,会检查类是否已被加载(自下而上),只要某个ClassLoader已加载即可,否则会自上而下加载该类。
      • Link:二进制字节码格式校验;静态变量默认值赋值;检验类、接口中属性和方法的存在,否则抛出NoSuchMethodError、NoSuchFieldError。
      • Initialize: 静态初始化代码、构造器代码以及静态属性的初始化;new对象;反射调用类中的方法;子类调用了初始化;JVM启动过程中指定的初始化类。
    • JVM垃圾回收过程:垃圾回收的频率和时间是检验程序运行好坏的标准(因为回收时要停顿应用);

      • 清理Eden和Survior的GC叫Minor GC;清理old区域的叫Major GC;清理整个Heap的叫Full GC;
    • 哪些对象可被回收:
      • 引用计数算法:每创建一个对象,给其分配一个引用计数变量,并置值为1;当把该变量赋值给任何其它变量时,引用计数加1;当一个实例对象的引用生命周期结束或被修改时,该实例的引用计数减1;一个引用计数为零的对象将被垃圾回收,同时该对象引用其它对象的引用计数器减1。

        • 缺点:无法检测出循环引用,如父对象有对子对象的引用,子对象也有对父对象的引用;
        • 优点:执行效率高(可程序执行中交织进行)
      • 可达分析算法:通过从对象GC ROOT的引用关系开始分析,逐层画出一个引用关系图节点图,最后剩余节点被认为没有引用到,可垃圾回收(还会进行两次标记,最后确定是否回收);GC ROOT对象包括:栈中引用对象;方法区中静态属性引用的对象;方法区中常量引用的对象;本地方法栈中JNI引用的对象;
      • 引用分类:强引用(如Object obj = new object()),软引用,弱引用,虚引用,引用计数和可达分析算法都是基于强引用。
      • 方法区中常量和类的回收:前者可通过可达性分析进行回收;后者需同时满足:该类所有实例是否都已回收?加载该类的ClassLoader是否已经回收?该类对应的java.lang.Class对象是否在别的地方有被引用(确定无反射访问)?
    • 垃圾回收算法
      • 标记-清除算法:使用从根集合(GC Roots)进行扫描,对存活的对象进行标记,完成标记后,再扫描整个空间,对没有标记的对象进行垃圾回收;该算法不需要移动对象,当存活对象较多时,该算法较为高效,但会产生内存碎片;
      • 复制算法:为克服句柄开销和解决内存开销,将堆分为对象区和空闲区,当对象区已满,将对象区的存活对象复制到空闲区,这样将原来的对象区转变为空闲区,又可存放新的对象;
      • 标记-整理算法:与标记-清除算法不同的是,在回收没有引用的对象后,将存活对象往左端空闲空间移动,同时更新对应指针;该算法成本较高,但解决了碎片问题;
      • 分代收集算法(目前JVM常用算法):根据对象存活的生命周期,将对象划分为新生代(有大量对象回收)、老生代(较少对象回收)和永久代(不回收),不同代采用不同回收算法;
        • 新生代分为eden+survior0+survior1(比例8:1:1),新生对象放在eden中,垃圾回收时(不一定eden满),将eden中存活的对象复制到survior0,然后清空eden,如果survior0满,则将eden和survior0中存活对象复制到survior1,然后清空eden和survior0,再交换survior1和survior0(此时survior0为空),保持survior1为空,再循环以上过程;如果survior1不能存放eden和survior0中存活对象时,将存活对象复制到老年代;如果老年代也满,即触发Major GC(Full GC),新生代和老年代都进行垃圾回收(新生代叫Minor GC,频率较高)。
        • 老年代存放生命周期较长的对象(在新生代经过多次垃圾回收仍然存活的对象),内存空间大概是新生代2倍或以上。
        • 持久代存放静态文件,如java类,垃圾回收对该区没有多大影响;如果应用动态生成有大量类或调用累,需要将该区设置一个较大空间。
    • 垃圾收集器
      • 串行收集器(Serial Collector,复制算法):新生代单线程收集器(标记和清除都是单线程),是client模式默认的GC,简单高效,也可通过-XX:+UseSerialGC强制指定别的GC方式;
      • 串行老年代收集器(Serial Old Collector,清除-标记算法):老年代单线程收集器;
      • 并行新生代收集器(ParNew Collector,停止-复制算法):新生代并行收集器,在多核CPU环境下,比串行收集器效率更高;
      • Parallel Scavenge收集器(停止-复制算法):并行收集器,高效利用CPU以获得高吞吐量(用户线程时间/(用户线程时间+GC线程时间)),server模式默认采用的GC方式;可用-XX:+UseParallelGC和-XX:ParallelGCThreads指定GC方式和GC线程数;
      • Parallel Old Scavenge收集器(停止-复制算法):老年代并行收集器(吞吐量优先);
      • CMS收集器(Concurrent Mark Sweep,标记清理算法):高并发,低停顿(GC回收时暂停应用),响应快,尤适合多CPU。
    • Scanvenge GC和Full GC
      • 当Eden申请新生成对象空间失败时会出发Scanvenge GC;
      • 4种情况触发Full GC:年老带已满(Tenured);持久代已写满(Perm);System.gc()被显示调用;上一次GC后Heap各域分配策略动态变化;
    • 执行引擎(Execution Engine):字节码由一个个指令单元组成,每个指令有一个字节的操作码和操作数组成,执行引擎逐一读取这些指令;但字节码语言是人类可以理解的语言,需要再将bytecode转化成JVM machine能执行的语言;
      • 解释器(Interpreter):逐一读取、解释、执行字节码指令;可迅速解释一条指令,但执行指令较慢;
      • JIT (Just-In-Time) compiler:作为补偿Interpreter的一种手段,首先运行Interpreter, 然后在合适的时机,将所有的bytecode转化为native code直接执行,而且native code保存在缓存中,所以执行效率很高。
      • HotSpot采用编译器和解释器混合使用,HotSpot会将一些频繁调用的方法和代码(也叫热点代码Hot Spot Code)在运行时编译成native code;HotSpot内置两个编译器:client compiler(C1)和server compiler(C2), 程序采用哪个取决于JVM的运行模式设置;
      • 为了平衡启动响应速度和运行效率,HotSpot会采取逐层编译机制(Tiered compilation),JDK1.7的server complier默认开启该机制:

第0层:程序解释执行,解释器不开启性能监控,可触发第一层编译。 
第1层:也称为C1编译(更好的编译速度),将字节码编译为本地代码,进行简单、可靠的优化。 
第2层:也称为C2编译(更好的编译质量),也是将字节码编译为本地代码,但会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。

    • 补充说明1:基本类型byte,boolean(1 byte),short,char(2 bytes),int,float(4 bytes),long,double(8 bytes);

JVM Optimization的更多相关文章

  1. Q&A to prepare interview of HSBC

    1.How do you keep updating lastest IT knowledge? 1).keep an eye on current project technology evetho ...

  2. Tomcat APR & Linux Optimization

    一.简介 APR(Apache portable Run-time libraries)模式:简单理解,就是从操作系统级别解决异步IO问题,大幅度的提高服务器的处理和响应性能, 也是Tomcat运行高 ...

  3. 关于JVM的类型和模式

    原文出处: 摆渡者 引言 曾几何时,我也敲打过无数次这样的命令: 然而之前的我都只关心过版本号,也就是第一行的内容.今天,我们就来看看第3行输出的内容:JVM的类型和工作模式. 其实说Server和C ...

  4. Java Performance Optimization Tools and Techniques for Turbocharged Apps--reference

    Java Performance Optimization by: Pierre-Hugues Charbonneau reference:http://refcardz.dzone.com/refc ...

  5. java源码剖析: 对象内存布局、JVM锁以及优化

    一.目录 1.启蒙知识预热:CAS原理+JVM对象头内存存储结构 2.JVM中锁优化:锁粗化.锁消除.偏向锁.轻量级锁.自旋锁. 3.总结:偏向锁.轻量级锁,重量级锁的优缺点. 二.启蒙知识预热 开启 ...

  6. java jvm和android DVM区别

      本文转自:http://blog.csdn.net/yujun411522/article/details/45932247   1.Android dvm的进程和Linux的进程, 应用程序的进 ...

  7. jvm.option是什么,它是如何加载的

    jvm.option是一些程序里边的java的配置参数的一个集合,不同的应用都会定义自己的jvm.options用来控制一些jvm的参数 以下,以elasticsearch为例,来说明它是如何加载的 ...

  8. JVM致命错误日志(hs_err_pid.log)分析

    当jvm出现致命错误时,会生成一个错误文件 hs_err_pid<pid>.log,其中包括了导致jvm crash的重要信息,可以通过分析该文件定位到导致crash的根源,从而改善以保证 ...

  9. New JVM Option Enables Generation of Mixed-Mode Flame Graphs

    转自 https://www.infoq.com/news/2015/08/JVM-Option-mixed-mode-profiles Java has added a new launch opt ...

随机推荐

  1. android layout文件优化

    性能优化1--UI优化 1.使用系统为我们提供了几个抽象的标签①include:重用include中layout属性指定一个外部布局文件,通过该方式则不需要把这个布局文件在该代码中重复的写一遍了. 若 ...

  2. Flask最强攻略 - 跟DragonFire学Flask - 第十五篇 Flask-Script

    其实本章就是为下一章做的铺垫啦,但是也要认真学习哦 Flask-Script 从字面意思上来看就是 Flask 的脚本 是的,熟悉Django的同学是否还记得Django的启动命令呢? python ...

  3. c#查找窗口的两种办法

    原文最早发表于百度空间2009-06-17 1.process.MainWindowTitle(这个只能获取一部分窗口)2.EnumWindows(用windows API)

  4. Idea 全局替换指定字符

    最近使用idea开发,刚接触不久,然后碰到需要全局替换的时候,懵逼了.之前使用eclipse 直接Ctrl+F 就可以操作了. 现在使用idea 摁Ctrl+F竟然只能搜,不能替换....尴尬的一匹. ...

  5. Guitar Pro里的编谱方式怎么用?

    今天来教大家如何使用Guitar Pro中的编谱方式来让我们的乐谱更加美观整齐耐看,我们一起get起来吧! 相信我们每一个人在使用Guitar Pro进行编曲创作时,都会碰到这种情况,在乐谱上,会看到 ...

  6. Java 基础 - 集合

    Set 集合 Set 集合通常不能记住元素的添加顺序.Set 集合不允许包含相同的元素. HashSet 是 Set 接口的实现类,按照 Hash 算法存储集合中的元素.HashSet 不是同步的,如 ...

  7. WordPress上传到互联网搭建

    1.建站流程: 1.购买域名 2.购买空间 3.解析绑定 4.上传安装 2.购买域名 域名的购买可以到相关域名出售的服务商那儿买,如阿里云,主机庙.这里就不做详细解释了 3.购买空间 域名的购买可以到 ...

  8. [python]windows截图

    Windows截图 截图:截取屏幕任意大小图片 下载pip install Pillow from PIL import ImageGrab # x1:开始截图的x坐标 # x2:开始截图的y坐标; ...

  9. 开机自动启动WEB服务,共享目录。

    最近工作中,需要共享一个目录,每次重启总要手动执行一下  nohup python -m SimpleHTTPServer 8000这个命令,想着实现让它开机自动启动,就一劳永逸了. 手动步骤如下: ...

  10. guxh的python笔记四:迭代

    1,可迭代对象iterable,迭代器iterator,生成器generator 可迭代对象iterable: 实现__iter__方法的类.__iter__方法返回iterator或者generat ...