【初探JVM】
JVM是现在面试中的常客,多是些概念性的东西需要把它记住,这个时候可不能拉跨!
先来几道题练练手,心里有个数
- 请你谈谈你对JVM的理解?
- Java8虚拟机和之前的变化更新?
- 什么是OOM?什么是栈溢出(StackOverFlowError)?怎么分析?
- JVM常用的调优参数有哪些?
- 内存快照如何抓取、怎么分析Dump文件?
- 谈谈JVM中,类加载器的认识?
- ……
懵逼了吧,那就来系统学习一波!
在学习的过程中会遇到很多抽象的概念,需要我们结合图式梳理分析,参考下面的网站:
JVM的位置
JVM的体系结构
类加载器
作用
加载Class文件
图示
分类
虚拟机自带的加载器
启动(根)加载器(BootStrap)
它不是Java类,因此它不需要被别人加载,它嵌套在Java虚拟机内核里面,也就是JVM启动的时候Bootstrap就已经启动,它是用C++写的二进制代码(不是字节码),它可以去加载别的类。
扩展类加载器(Extension)
应用程序(系统)加载器(System)
示例
1 | public class Person { |
双亲委派机制
描述
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
AppClassLoader——>ExtClassLoader——>Bootstrap(最终执行)
目的
保证安全性
实例
1 | package java.lang; |
执行结果程序会报错:在类 java.lang.String
中找不到 main
方法
分析:程序不会先执行在自己创建的类中的方法,而是先委托给其父类加载器,最后在 jdk 自带的 java.lang
中找到要完成的类加载任务,会选择该类执行而不是自己创建的类,进而由于找不到 main
方法而报错。
- 类加载器收到类加载请求
- 将这个请求向上委托给父类加载器完成,一直向上委托直到根类加载器
- 启动加载器检查是否能够加载当前这个类,能加载就结束,使用当前的类加载器,否则就抛出异常,通知子加载器进行加载
- 重复上一步
能不能自己写个类叫
java.lang.System
?答案:通常不可以,但可以采取另类方法达到这个需求。
解释:为了不让我们写System类,类加载采用委托机制,这样可以保证爸爸们优先,爸爸们能找到的类,儿子就没有机会加载。而System类是Bootstrap加载器加载的,就算自己重写,也总是使用Java系统提供的System,自己写的System类根本没有机会得到加载。但是,我们可以自己定义一个类加载器来达到这个目的,为了避免双亲委托机制,这个类加载器也必须是特殊的。由于系统自带的三个类加载器都加载特定目录下的类,如果我们自己的类加载器放在一个特殊的目录,那么系统的加载器就无法加载,也就是最终还是由我们自己的加载器加载。
沙箱安全机制
Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。沙箱主要限制系统资源访问,那系统资源包括什么?——CPU、内存、文件系统、网络。不同级别的沙箱对这些资源访问的限制也可以不一样。
所有的Java程序运行都可以指定沙箱,可以定制安全策略。
https://www.cnblogs.com/MyStringIsNotNull/p/8268351.html
Native
1 | //简化版 |
native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
JNI是Java本机接口(Java Native Interface),是一个本机编程接口,它是Java软件开发工具箱(java Software Development Kit,SDK)的一部分。JNI允许Java代码使用以其他语言编写的代码和代码库。Invocation API(JNI的一部分)可以用来将Java虚拟机(JVM)嵌入到本机应用程序中,从而允许程序员从本机代码内部调用Java代码。
JNI作用:扩展Java的使用,融合不同的编程语言为Java所用
在最终执行的时候,通过 JNI 加载本地方法库中的方法
PC寄存器
程序计数器是一个记录着当前线程所执行的字节码的行号指示器。
JAVA代码编译后的字节码在未经过JIT(实时编译器)编译前,其执行方式是通过“字节码解释器”进行解释执行。简单的工作原理为解释器读取装载入内存的字节码,按照顺序读取字节码指令。读取一个指令后,将该指令“翻译”成固定的操作,并根据这些操作进行分支、循环、跳转等流程
方法区
方法区是被所有线程所共享的,所有字段、方法字节码、特殊方法(构造函数、接口代码)等在此定义,属于共享空间。
- 静态变量:
static
- 常量:
final
- 类信息:
Class
- 常量池
栈
程序员学习思想:
程序 = 数据结构 + 算法 √ (持续学习)
程序 = 框架 + 业务逻辑 ×(很容易被淘汰,吃饭用的)
一个小问题:为什么 main
方法先执行,最后结束?
一个图解释清楚:
再想想递归调用出现栈溢出是怎么肥四?
对于栈来说,不存在垃圾回收问题
栈存放的内容
- 8大基本类型
- 对象引用
- 实例的方法
类实例化的过程
三种JVM
了解即可
- Sun公司 - HotSpot
- BEA - JRockit
- IBM - J9VM
堆
Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。
类加载器读取了类文件后,一般会把什么东西放在堆中?
- 类
- 方法
- 常量
- 变量
保存引用类型的真实对象
堆内存中还要细分为三个区域:
- 新生区(伊甸园区)
- 养老区
- 永久区
GC垃圾回收主要是在伊甸园区和养老区!
堆内存满了会爆出 OutOfMemoryError:Java heap space
JDK8以后,永久区——>元空间
新生区、老年区
新生区
对象诞生、成长甚至死亡的地方
伊甸园区
所有对象都是在伊甸园区
new
出来的幸存区
- 0区
- 1区
经过研究,99%的对象都是临时对象!
永生区(元空间)
这个区域是常驻的,用来存放 JDK 自身携带的 Class 对象。Interface 元空间,存储的是Java运行时的一些环境或类信息,这个区域不存在 GC。关闭 JVM 时这个区域的内存被释放。
- JDK1.6 之前:永久带,常量池在方法区中
- JDK1.7 :永久带,但是慢慢退化了(去永久带),常量池在堆中
- JDK1.8之后:无永久带,常量池在元空间
堆内存调优
Dump文件:
使用命令 -XX:HeapDumpOnxxxError
、-XX:HeapDumpOnxxxException
可以生成关于异常的文件,使用插件 Jprofilter 可以对其进行分析
排除OOM错误故障的方法:
- 能够看到代码第几行出错:内存快照分析工具,MAT(Eclipse)、Jprofiler(IDEA)
- Debug
MAT、Jprofiler作用
- 分析Dump内存文件,快速定位内存泄露
- 获得堆中的数据
- 获得大的对象
- ……
GC:垃圾回收
一些GC的问题
- JVM的内存模型和分区(详细到每个区放什么)
- 堆里面的分区有哪些?Eden、from、to、老年区,说说他们的特点
- GC算法有哪些?怎么用?
- 轻GC 和 重GC 分别在什么时候发生
GC的作用区域
JVM在进行GC时,并不是对新生代、幸存区(from、to)、老年去进行统一回收,大部分回收的都是新生代。
GC的分类
- 轻GC(普通GC)
- 重GC(全局GC)
GC的算法
1.引用计数法
每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。
2.复制算法
当一个对象经历了 15次 GC还没有被清除,就会进入老年代。
(可以使用参数 -XX:MaxTenuringThreshold=?
来进行调节)
- 好处:没有内存碎片
- 坏处:浪费了空间
- 使用场景:对象存活度较低的区域—新生区。
3.标记清除算法
- 优点:不需要浪费额外的空间
- 缺点:两次扫描,严重浪费时间,会产生内存碎片
4.标记压缩算法
对标记清除算法的优化
总结
内存效率
复制算法 > 标记清除算法 > 标记压缩算法
内存整齐度
复制算法 = 标记压缩算法 > 标记清除算法
内存利用率
标记压缩算法 = 标记清除算法 > 复制算法
- 思考:难道没有最优的算法嘛?
- 答案:莫得,只有最合适的
- GC:分代收集算法
完结撒花~~~~~~~~~
狂神,永远滴神!!!
完了之后抽空深入了解JVM,看《深入理解JVM原理》
参考
狂神说Java:https://www.bilibili.com/video/BV1iJ411d7jS
程序媛想事儿:https://www.cnblogs.com/lanxuezaipiao/p/4138511.html
不止吧:https://www.cnblogs.com/b3051/p/7484501.html
re-phoenix:https://www.cnblogs.com/manayi/p/9290490.html
春_:https://blog.csdn.net/weixin_43736084/article/details/103937547