学习笔记-5.JVM

5. JVM

5.1 初识JVM

5.1.1 JDK、JRE和JVM

官网原图

JDK、JRE和JVM

5.1.2 源码到类文件
javac Person.java--->Person.class

Person.java -> 词法分析器 -> tokens 流 -> 语法分析器 -> 语法树/ 抽象语法树 -> 语义分析器
-> 注解抽象语法树 -> 字节码生成器 -> Person.class 文件
Person.class是个16进制文件,可用sublime打开,其结构可从官方文档查看如下:


class格式说明.png
5.1.3 类加载机制
类加载机制

装载:

(1)通过一个类的全限定名获取定义此类的二进制字节流。

(2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

(3)在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中。

链接

(1)验证:保证被加载类的正确性文件格式验证/元数据验证/字节码验证/符号引用验证。

(2)准备:为类的静态变量分配内存,并将其初始化为默认值。 默认值不是类设定的默认值而是数值类型的默认值,例如:
static int a = 0 此时给a 分配空间,并初始化为0。 int类型的默认值均为0.

(3)解析:把类中的符号引用转换为直接引用这些数据的访问入口。 就是将class的二进制数据转化为地址。

初始化

对类的静态变量,静态代码块执行初始化操作。 此时设置a=10;

5.1.4 类加载器
类加载器

双亲委派模型
定义:如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

优势:Java类随着加载它的类加载器一起具备了一种带有优先级的层次关系。比如,Java中的Object类,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object在各种类加载环境中都是同一个类。如果不采用双亲委派模型,那么由各个类加载器自己取加载的话,那么系统中会存在多种不同的Object类。

双亲委派模型有多种打破方式:

  1. 自己实现ClassLoad类,重写loadClass方法

5.2 运行时数据区

5.2.1 官网解读

官网解读

官网解读

图解表示

方法区和堆的生命周期与虚拟机绑定在一起,其他与线程有关。

5.2.2 方法区

方法区:

  1. 方法区是各个线程共享的内存区域,在虚拟机启动时创建。

  2. 用于存储已被虚拟机加载的类信息(类的描述信息、创建的时间,作者)、常量、静态变量、即时编译器编译后的代码等数据。

  3. 虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却又一个别名叫做Non-Heap(非堆),目的是与Java堆区分开来。

  4. 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

  5. 方法区在JDK 8中就是Metaspace【元空间】,在JDK6或7中就是Perm Space【永久代】。

  6. Run-Time Constant Pool(运行时常量池)在方法区分配。

  7. 方法区是非线程安全的。

5.2.3 堆

  1. 堆是Java虚拟机所管理内存中最大的一块,在虚拟机启动时创建,被所
    有线程共享,每个进程只有一个堆。

  2. Java对象实例以及数组都在堆上分配。

  3. 当堆无法满足内存分配需求时,将抛出OutOfMemoryError异常。

5.2.4 Java虚拟机栈

Java虚拟机栈

  1. 虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态。换句话说,一个Java线程的运行状态,由一个虚拟机栈来保存,所以虚拟机栈肯定是线程私有的,独有的,随着线程的创建而创建。

  2. 每一个被线程执行的方法,为该栈中的栈帧,即每个方法的执行对应一个栈帧。

  3. 调用一个方法,就会向栈中压入一个栈帧;一个方法调用完成,就会把该栈帧从栈中弹出。

  4. 如果调用的方法过多,栈的深度不够就会抛出StackOverflowError异常。

理解Java虚拟机栈

栈帧

  1. 每个栈帧对应一个被调用的方法,可以理解为一个方法的运行空间。

  2. 每个栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、动态链接(运行时常量池的引用、把类中的符号引用转换为直接引用)、方法返回地址(Return Address)和附加信息。

理解栈帧

对Class进行反编译,生成字节码指令

javap -c Person.class > Person.txt
理解栈帧
再次理解虚拟机栈
5.2.5 程序计数器

程序计数器:

一个JVM进程中有多个线程在执行,而线程中的内容是否能够拥有执行权,是根据CPU调度来的。假如线程A正在执行到某个地方,突然失去了CPU的执行权,切换到线程B了,然后当线程A再获得CPU执行权的时候,怎么能继续执行呢?这就是需要在线程中维护一个变量,记录线程执行到的位置。

  1. 程序计数器占用的内存空间很小,由于Java虚拟机的多线程是通过线程轮流切换,并分配处理器执行时间的方式来实现的,在任意时刻,一个处理器只会执行一条线程中的指令。因此,为了线程切换后能够恢复到正确的执行位置,每条线程需要有一个独立的程序计数器(线程私有)。
  2. 如果线程正在执行Java方法,则计数器记录的是正在执行的虚拟机字节码指令的地址。
  3. 如果正在执行的是Native方法,则这个计数器为空。
5.2.6 本地方法栈

本地方法栈

如果当前线程执行的方法是Native类型的,这些方法就会在本地方法栈中执行。


我们的旅程

5.3 JVM内存模型

内存模型

图解表示

触发讲对象拷贝到old区是,对象过大,或者经过15次GC,仍然存活。

Young区:
Young区分为两大块,一个是Survivor区(S0+S1),一块是Eden区。Eden:S0:S1=8:1:1。 划分s0 和s1是为了解决空间碎片问题。

Eden区:
正常对象创建所在区域,大多数对象“朝生夕死”,避免频繁触发GC

Survivor区:

  1. Survivor区分为两块S0和S1,也可以叫做From和To。
  2. 在同一个时间点上,S0和S1只能有一个区有数据,另外一个是空的。
  3. 当某个对象值太大,s区放不下时,会触发担保机制:从old区借用一些内存空间,来存放,知道他被回收或者超过15次被移动到old区。

Old区:

一般Old区都是年龄比较大的对象,或者相对超过了某个阈值的对象。

JVM内存模型.jpg

结合工具体验与验证:
插件下载链接

  1. jvisualvm 在bin目录下打开。
  2. 堆内存溢出:设置参数比如-Xmx20M -Xms20M
  3. 方法区内存溢出:-XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=50M
  4. 虚拟机栈溢出:-Xss128k

5.4 垃圾回收

5.4.1 如何确定一个对象是垃圾
  1. 引用计数法:一旦相互持有引用,就导致对象永远没法被回收。
  2. 可达性分析:由GC Root出发,开始寻找,看看某个对象是否可达。

GC Root:类加载器、Thread、本地变量表、static成员、常用引用、本地方法栈中的变量等

垃圾回收算法

  1. 标记清除


    标记清除前

    标记清除后

扫描整个内存空间,会造成大量空间碎片。

  1. 复制


    复制前

    复制后

解决空间碎片问题,造成空间浪费。

  1. 标记整理


    标记整理前

    标记整理后

young区用复制算法,old区用标记整理或者标记清楚

5.4.2 分代收集算法

Young区:复制算法

Old区:标记清除或标记整理

5.4.3垃圾收集器
垃圾收集器
  1. Serial


    Serial
  1. Serial Old

  2. ParNew


    ParNew
  1. Parallel
    相比ParNew,更加关注吞吐量

  2. Parallel Old

  3. CMS
    更加关注停顿时间


    CMS
  1. G1
    更加关注停顿时间:用户可以设置一个预期的停顿时间


    image.png
5.4.4 相关知识梳理

垃圾收集器分类

垃圾收集器分类

吞吐量和停顿时间

吞吐量和停顿时间

如何选择收集器

如何选择收集器

如何开启收集器

如何开启收集器

5.5 工欲善其事必先利其器

5.5.1 JVM参数
  1. 标准参数
  2. -X参数
  3. -XX参数
-XX:[+/-] -XX:+UseG1GC
-XX:<name>=<value> -XX:InitialHeapSize=100M

(4)其他参数

-Xms100M ===>-XX:InitialHeapSize=100M
-Xmx100M -Xss100
JVM参数
5.5.2 JVM命令
  1. jps: 当前的java进程
  2. jinfo: 查看某个java进程目前的参数设置的情况
  3. jstat: 查看java进程统计性能
  4. jstack:查看当前java进程的堆栈信息
  5. jmap:打印出堆转存储快照
jmap -heap PID 
dump出堆内存相关信息:jmap -dump:format=b,file=heap.hprof PID
5.5.3 常用工具

1.jconsole

  1. jvisualvm

  2. arthas

  3. mat/perfma:内存相关的信息

  4. gceasy.io/gcviewer: 垃圾回收

5.6 性能优化

性能优化指南

5.6.1 JVM全局理解

JVM全局理解

5.6.2 OOM

通过MAT分析dump文件,定位OOM。

5.6.3 GC优化

通过不断调整,观察GC日志的吞吐量和停顿时间,寻找最佳值

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+UseG1GC
-Xloggc:gc.log
gceasy.io

主要就是调整各种参数,垃圾收集器--->查看吞吐量和停顿时间的变量 高吞吐量,低停顿时间。

性能优化.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 堆(Heap) 概述 ● 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域。● Java堆区在JV...
    村里一枝花丶阅读 351评论 0 1
  • 0. 结构图 1. 运行时数据区总览 类加载子系统:加载的类信息存放于方法区当中,方法区当中可能还包括运行时常量池...
    BlueSocks阅读 392评论 0 1
  • 本文所有内容来于:http://stuq.com/a/100ww java代码是如何执行的 java代码是运行于j...
    良辰美景TT阅读 2,741评论 0 89
  • 什么是Java虚拟机 各个硬件平台本身不支持Java字节码,Java虚拟机就是在不同硬件平台上支持Java字节码的...
    Charles1993阅读 245评论 0 3
  • 一、JVM内存结构 1. 程序计数器(PC寄存器) 记录指令执行位置。当前线程正在执行的那条字节码指令的地址。如果...
    羊咩咩a阅读 404评论 0 0