JVM基础知识汇总

1.jvm是什么

       Java Virtual Machine(Java虚拟机),它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的.

       本文jvm是基于jdk7写的,关于jdk8的jvm,和jdk7的稍有不同,详见文章末尾链接


2.jvm能做什么

       java语言之所以可以跨平台,就是jvm屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行.Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行.这就是Java的能够“一次编译,到处运行”的原因.


3.jvm分类

3.1 SUN公司(已被oracal收购)有好几款虚拟机,包括hotSport
3.2 BEA公司:jRockit(专注于服务器端应用)
3.3 IBM公司:J9 VM(用于作为IBM公司各种java产品的执行平台)
3.4 微软:Microsoft JVM(为了在浏览器中运行java程序,已经被sun公司搞死了)
3.5 其他(还有很多)

最常熟知的就是sun公司的hotSpotVm,也就是我们常用的vm.
我也是主要以这个为重点来展开的


4.jvm内存区域(HotSpot)

这里写图片描述

4.1 程序计数器(线程私有)

       占用很小的内存空间,可以看成是当前线程所执行的字节码的行号指示器,所以他是每个线程私有的,各线程的计数器互不影响,独立存储

4.2 java栈(线程私有)

4.2.1 java虚拟机栈

       执行java方法

4.2.2 本地方法栈

       执行本地方法(可以理解为java同c语言的接口)

       每个方法在执行的同时都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口的信息.

局部变量表:
------存储方法中的局部变量(包括在方法中声明的非静态变量以及函数形参)
------对于基本数据类型的变量,则直接存储它的值,对于引用类型的变量,则存的是指向对象的引用.
------局部变量表的大小在编译器就可以确定其大小了,因此在程序执行期间局部变量表的大小是不会改变的.

操作数栈:
------所有计算过程都是在借助于操作数栈来完成的.

方法出口:
------方法返回地址,当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。

4.3 java堆(线程共享)

       虚拟机启动的时候创建,主要用来存放对象实例,GC的主要阵地.

4.3.1 新生代

------Eden
------Form Survivor
------To Survivor

4.3.2 老年代

4.4 方法区(线程共享)

非堆永久代(hotSpot特有),为了让垃圾收集器像管理堆一样管理这部分内存.
方法区存储了每个类的信息,比如:

4.4.1.Classloader 引用
4.4.2.字段数据(每个字段的字段名,类型,修饰符,属性)
4.4.3.方法数据(每个方法的方法名,返回值类型,参数类型,修饰符,属性)
4.4.4.方法代码(每个方法的字节码,操作数栈大小,局部变量大小,局部变量表,异常表,每个异常处理器,开始点,结束点,异常处理代码的程序计数器(PC)偏移量,被捕获的异常类对应的常量池下标)

       因为所有线程共享同一个方法区,因此访问方法区数据的和动态链接的进程必须线程安全。如果两个线程试图访问一个还未加载的类的字段或方法,必须只加载一次,而且两个线程必须等它加载完毕才能继续执行。

4.5 运行时常量池

jvm7之前属于方法区,用来存储数值型常量,字段引用,方法引用,属性
关于常量池,字符串常量池,运行时常量池区别,请戳这里:
区别

java内存对象模型如下图
这里写图片描述

5.jvm垃圾收集算法

5.1 标记-清除算法

先标记需要回收的对象,后统一清除,缺点是效率不高,而且会产生大量不连续的内存碎片,导致后面的大对象无法存储,从而导致再一次收集.

5.2 复制算法(适用于对象存活率较低的内存区域,比如新生代)

先将可用内存划分成两块A B,每次使用一块A,当这块A满了,就将这块中还存活的对象放在另一块B上,然后一次性清理掉A.复制算法简单粗暴效率高.

如果将AB的内存比例设置为1:1,那么相当于将可用内存减半了,太不划算,考虑到98%的对象都是朝生夕死,所以将新生代分为三块:Eden,Form Survivor,To Survivor,默认8:1:1

(两个survivor,是为了保证任何时候都有一个survivor是空的)

5.3 标记-整理算法(适用于对象存活率高的内存区域,比如老年代)

先标记需要回收的对象,然后让所有存活的对象都向一端移动,最后清理掉端边界以外的内存,这样一次收集后,空闲的内存会比较连续,更容易存放大对象.
同样的,这个算法,效率更低.

6.JVM垃圾收集器

首先说收集器的目标:低停顿,高吞吐,大覆盖
a. 停顿时间
停顿时间越短就越适合于用户交互的程序,良好的响应速度能提升用户体验。
b. 吞吐量
高吞吐量则可以高效率利用CPU时间,尽快完成运算任务。适合在后台计算而不需要太多交互的任务。
c. 覆盖区
在达到前面两点的情况下,尽量减少堆的内存空间,可以获得更好的空间局部性。

6.1 Serial收集器 ['sɪərɪəl]

这里写图片描述
单线程收集器.
特点1:简单高效
特点2:Stop The Word.即收集垃圾的时候,会把其他线程全部停掉
“-XX:+UseSerialGC” : 该参数用来显示的添加串行垃圾收集器

6.2 Parnew收集器['pɑːnjuː]

这里写图片描述
是Serial收集器的多线程版本
特点:除了Serial收集器,目前只有Parnew收集器能与CMS收集器配合工作
“-XX:+UseConcMarkSweepGC”:指定使用CMS后,会默认使用ParNew作为新生代收集器
“-XX:+UseParNewGC”:强制指定使用ParNew收集器
“-XX:ParallelGCThreads”:指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同

6.3 Parallel Scavenge收集器 ['pærəlel]['skævɪndʒ]

特点1:关注点在于吞吐量,而其他线程一般都注重缩短垃圾回收时,用户停顿时间
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
特点2:多了一个GC自适应调节策略,-XX:+UseAdaptiveSizePolicy
“-XX:MaxGCPauseMillis”:控制最大垃圾收集停顿时间
“-XX:GCTimeRatio”:直接设置吞吐量大小(0-100),默认值是99,就是允许最大1%(即 1/(1+99))的垃圾收集时间

6.4 Serial Old收集器

Serial收集器的老年代版本,
特点:单线程收集器.新生代采取复制算法,老年代采取标记整理算法

6.5 Parallel Old收集器

这里写图片描述
Parallel Scavenge收集器的老年代版本,1.6开始出现
特点:多线程,标记整理算法,主要是和Parallel Scavenge配合使用
“-XX:+UseParallelOldGC”:指定使用Parallel Old收集器。

6.6 CMS收集器(Concurrent Mark Sweep)

这里写图片描述
标记清除算法
特点:回收停顿时间短,并发收集
“-XX:+UseConcMarkSweepGC”: 指定使用CMS收集器(用了这个后,年轻代会默认使用ParNew收集器)
“-XX:CMSInitiatingOccupancyFraction=75” :是指设定CMS在对内存占用率达到75%的时候开始GC(因为CMS会有浮动垃圾,所以一般都较早启动GC)
“-XX:+UseCMSInitiatingOccupancyOnly”:只是用设定的回收阈值(上面指定的75%),如果不指定,JVM仅在第一次使用设定值,后续则自动调整.
一般情况下,"-XX:CMSInitiatingOccupancyFraction=75"和"-XX:+UseCMSInitiatingOccupancyOnly"是配合使用的

CMS缺点1:并发导致cpu资源敏感,尤其是4C以下,CMS默认的收集线程数量是 = (CPU数量 + 3)/4,所以说核数越大,CMS并发对用户的影响越小
解决 : 多核cup考虑一下
CMS缺点2:浮动垃圾(并发清除的时候产生的垃圾)可能导致再一次FullGC(启动Serial Old收集器),这次收集时间较长
解决 : “-XX:CMSInitiatingOccupancyFraction”:设置CMS预留内存空间,就是给浮动垃圾用的,当这块内存不够用的时候,就会再次导致FullGC
CMS缺点3:产生大量内存碎片(标记清除算法 )
解决1: “-XX:+UseCMSCompactAtFullCollection”,默认开启,用于fullGC前的合并整理,但这个整理过程需要停顿
解决2: “-XX:+CMSFullGCBeforeCompaction”,默认0,当执行n次不压缩的fullGC后,下次FullGC带压缩

总而言之,服务器内存越大,核数越多,就越适合用CMS

6.7 G1收集器

这里写图片描述

堆空间分割收集

特点1:使用并发让GC的时候,应用程序继续执行(G1在另一个CPU上运行)
特点2:分代收集,但不需要其他收集器配合,能够采用不同方式处理不同时期的对象,但新生代和年老代不再是物理隔离,它们都是一部分Region(不需要连续)的集合
特点3:整体标记整理,局部复制算法(堆划分为多个大小相等的独立区域Region),总之不是标记清除算法
特点4:做到实时垃圾收集(RTSJ),即可预测的停顿,建立可预测的停顿时间模型,可以明确指定M毫秒时间片内,垃圾收集消耗的时间不超过N毫秒,这样在收集的时候就可以有选择的在用户设置的时间范围内回收最优先需要回收的region(G1跟踪各个Region获得其收集价值大小,在后台维护一个优先列表)
特点5:整体优于CMS的低停顿

“-XX:UseG1GC”:指定使用G1收集器.
“-XX:MaxGCPauseMillis”:为G1收集器设置暂停时间目标,默认值为200毫秒
“-XX:G1HeapRegionSize”:设置每个Region大小,范围1MB到32MB;在最小Java堆时可以拥有大约2048个Region

这里写图片描述

注:
在G1中,还有一种特殊的区域,叫Humongous区域。 
如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。
这些巨型对象,默认直接会被分配在年老代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。
为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。
如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。
为了能找到连续的H区,有时候不得不启动Full GC

垃圾收集器关系图:

这里写图片描述

jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.9 默认垃圾收集器G1

7.jvm可视化

8.jvm调优

-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-XX:+PrintGCApplicationStoppedTime // 输出GC造成应用暂停的时间
-Xloggc:../logs/gc.log 日志文件的输出路径
-XX:+HeapDumpOnOutOfMemoryError //发生OOM的时候自动dump堆栈方便分析

9.jvm常见问题

       9.1 如果A和B对象循环引用,是否可以被GC?
       9.2 如何判断对象是否需要回收,有哪几种方式?
       9.3 Java中能不能主动触发GC?
       9.4 Java中的内存溢出是什么,和内存泄露有什么关系?
       9.5 Java中的内存溢出是什么,和内存泄露有什么关系?
       9.6 ClassLoader的类加载方式

10.jvm–jdk1.8

参考:
https://blog.csdn.net/joeyon1985/article/details/39080125

11.jvm本地小测试

参考:
https://blog.csdn.net/universe_ant/article/details/58585854

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499710.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java程序员常用查询和学习的网站

常用的一些程序员相关网站,在这里记录下,大家一起学习 置顶: 唯品会java开发手册(基于阿里巴巴java开发手册) pdf转word(推荐用这个,国外的) pdf转word(国内的这个有大小限制) 1.生成…

Longest Palindromic Substring Part II

Longest Palindromic Substring Part II 给定一个字符串 S, 找出字符串S中的最长回文子字符串. 注意: 这是关于:Longest Palindromic Substring.的第二篇文章了.在这里,我们讨论一种可以再线性时间内找到字符串中最长回文子字符串的一种算法(Manacher’s algorithm).请先阅读第…

Java反射基础(一)--Class对象获取

Classes Java中,任何一个对象要么是一个引用类型要么是基本数据类型.引用类型指的是那些直接或间接 Java.lang.Object的类.Classse,enum,和接口都是应用类型.基本类型是一个固定的集合,它包括: boolean, byte,short, int, long,char,float, double. java.lang.String和所有的基…

Java反射基础(二)--Fileds对象的使用

在说Filed之前,我们先来了解一下Member接口. 反射中定义了一个接口 java.lang.reflect.Member . java.lang.reflect.Field, java.lang.reflect.Method, 和java.lang.reflect.Constructor 都实现了该接口.我们将在接下来的部分介绍这些类.对于每个Member, 我们都会介绍相关的API…

Java反射基础(三)--Methods对象的使用

Method 原文地址:http://docs.oracle.com/javase/tutorial/reflect/member/method.html 1.获得方法类型信息 一个方法的声明包括方法名,修饰符, 参数, 和返回类型,同时还有一些方法可能抛出的异常. 类 java.lang.reflect.Method 提供了一种方式让我们可以得到方法的这些信息. …

Guice基本用法

本文适合对依赖注入有相对了解的读者,文章中对于部分名词未作详细解释。对于没有恰当的中文与之对应的英文内容,遂未翻译 Guice简介 Guice 简介,本文中的内容也是参考该文档完成,如有不一致,以该文为准。 快速上手 …

Guice之Servlet基础

如果读者对于Guice没有大体的了解,可以参考本人的另一篇Guice基础文章 Guice 提供了一个完整的体系使得我们在web应用中也可以使用它作为依赖注入的工具. 为什么使用 Guice : 使用Guice的好处: 构造函数注入类型安全的, 方便的配置方式(只需要在web.xml中进行很…

矩阵 I : 矩阵基础

学习机器学习, 基础的线性代数知识是必备的基础功, 对于线性代数的探索, 矩阵是线性代数的主要研究对象. 今天我们就开始学习一下矩阵的基础知识. 这是本人关于线性代数矩阵的第一篇分享. 章节目录 矩阵及其基本运算 1.1 矩阵定义 1.2 矩阵基本运算(,-,*) 1.3 转置矩阵 1…

矩阵 II : 线性组的线性相关性

学习机器学习, 基础的线性代数知识是必备的基础功, 对于线性代数的探索, 向量组也是线性代数的重要基础. 今天我们就开始学习一下线性代数中重要的向量组知识. 这是本人关于线性组的线性相关性的学习分享. 章节目录 相关性基本概念 1.1 相性相关和线性无关 1.2 相性相关性的…

汇编语言笔记(一):基础

章节目录 简单程序 使用段简单字符串处理程序使用 bx, si, di, bp 寄存器寻址寻址方法指明数据长度div指令 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 本文中所有程序均在DOSBox下使用MASM, LINK编译运…

汇编学习笔记(二):转移指令

章节目录 转移指令原理 jmp 指令 jcxz 指令 loop 指令 ret 和 retf 指令 call 指令 callret 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 本文中所有程序均在DOSBox下使用MASM, LINK编译运行 转移指令…

汇编语言笔记(三): 标志寄存器

章节目录 简介 ZF 标志寄存器PF 标志寄存器SF 标志寄存器CF 标志寄存器OF 标志寄存器几条相关指令DF 标志寄存器PUSHF and POPF 标志寄存器 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 简介 8086 CPU…

汇编语言笔记(四):内中断

汇编语言笔记:内中断 章节目录 概念 中断过程示例: 0 号中断处理 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 概念 中断信息: 任何一个通用 CPU 都具备一种能力, 可以在执行完当前正在执行的指令之…

sync.Map 源码学习

golang 线程安全的 Map 作者水平有限,而并发博大精深. 如文章中有任何错误, 希望读者不吝指出.谢谢! 章节目录 Map 基本类型定义StoreLoadDeleteRange Map 基本类型定义## Map 这里我们先看一下 Map 都涉及到那些类型. type Map struct {// 互斥锁. 用于互斥的读写 dirty.…

ASN.1 学习

ASN.1 章节目录 简介常用数据类型 2.1 常见的简单类型 2.2 结构类型Basic Encoding RulesDistinguished Encoding Rules编码示例 5.1 BIT STRING 5.2 IA5String 5.3 INTEGER 5.4 NULL 5.5 OCTET STRING 5.6 UTCTime 5.6 OBJECT IDENTIFIER编码 Name (X.501 type) 参考 http://…

证书体系: PFX 文件格式解析

原文同时发布于本人个人博客: https://kutank.com/blog/cert-pfx/ 章节目录 PFX 简介PFX 格式解析 2.1 最外层结构 2.2 AuthenticatedSafe 结构 参考 https://tools.ietf.org/html/rfc7292. PFX 简介## 以下引用自维基百科 在密码学中,PKCS #12 定义了…

C10K 非阻塞 Web 服务器

本文由作为 Going Concurrency in Go 的作者 Nathan Kozyra 撰写, 解决了互联网上最著名,最受尊敬的挑战之一, 并试图通过核心 Go 包来解决它. 原文地址: https://hub.packtpub.com/c10k-non-blocking-web-server-go/ 我们已经构建了一些可用的应用程序,并且可以在日常使用的真…

MD5 算法描述及实现

MD5 算法的原理及实现 章节目录 简介算法描述 实现 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 简介## Wiki对其的描述: MD5消息摘要算法(英语:MD5 Message-Digest Algorithm&…

SHA 算法描述与实现

SHA 算法的原理及实现 章节目录 简介算法描述 2.1 数据准备 2.1.1 数据填充 2.1.2 数据分块 2.1.3 设置初始 Hash 值 2.2 Hash 计算 2.2.1 SHA-1 2.2.2 SHA-256 2.2.3 SHA-512实现 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者…

SHA算法描述及实现

SHA 算法的原理及实现 章节目录 简介算法描述 2.1 数据准备 2.1.1 <数据填充 2.1.2 数据分块 2.1.3 设置初始 Hash 值 2.2 Hash 计算 2.2.1 SHA-1 2.2.2 SHA-256 2.2.3 SHA-512实现<b>作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, …