JVM入门学习
一引言
在面试中Java虚拟机JVM的相关知识是必须会被问到的,如下面几个问题,
- 谈谈对JVM的理解
- 谈谈对JVM中的ClassLoader类加载器的理解,JVM是怎么加载class文件的?
- 什么是OOM?什么时候会出现StackOverFlowError和OutOfMemoryError,写代码实现一下?
- JVM的常用参数调优了解吗?
- 内存快照抓取和MAT分析hprof文件干过吗?
- 谈谈垃圾回收机制
- .........
所以很有必要好好学习以下JVM相关的知识
二基本
什么是JVM?
是JAVA虚拟机,是一种用于计算设备的规范,是虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的(百度百科)。
JAVA语言最大的一个特点是与平台的无关性,而JVM是实现这一特点的关键。
JVM运行在操作系统之上,与硬件没有直接的交互。
三类加载
JVM把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,形成可以被JVM直接使用的java类型的过程。
类加载过程:加载->验证->准备->解析->初始化。
类加载器:
- BootStrap ClassLoader:启动类加载器,c++实现,负责加载存放在\lib下的class文件,或者被-Xbootclasspath参数所指定的路径中的
- Extension ClassLoader:扩展类加载器,负责加载\lib\ext路径下的class文件
- Application ClassLoader:应用类加载器,负责加载用户类路径(classpath)上所指定的class文件,
双亲委派模型,要求除了顶层的启动类加载器外,其他的类加载器必须有父类加载器。
双亲委派加载过程:当一个类加载器收到加载类的请求时,先把这个请求委派給父类加载器完成,只有当父类加载器无法完成加载任务时,才由子类加载器尝试加载。
这样设计的好处是什么?
四jvm运行时内存数据
4.1 PC寄存器
每个线程都有一个程序计数器,是线程私有的。
4.2 栈
在线程创建时创建,生命周期跟随线程的生命周期,线程结束栈内存也会释放。
模拟一个StackOverFlowError:
1 package cn.np.jvm; 2 3 /** 4 * @author np 5 * @date 2018/9/10 6 * 7 * 实验StackOverFlowError 8 */ 9 public class StackOverFlowErrorDemo { 10 11 public void func(){ 12 func(); 13 } 14 15 public static void main(String[] agrs){ 16 StackOverFlowErrorDemo stackOverFlowErrorDemo=new StackOverFlowErrorDemo(); 17 stackOverFlowErrorDemo.func(); 18 } 19 }
4.3 方法区
各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。
- Java虚拟机规范把方法区描述为堆的一个逻辑部分
- 有一个别名叫非堆
- 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常
4.4 堆
对于大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块。这一块内存区域被所有线程共享,是在虚拟机启动时创建。
- 存放对象实例,几乎所有的对象实例以及数组都在这里分配内存
- 垃圾收集器管理的主要区域
- 物理上可以是不连续的内存空间,逻辑上是连续的
VMoptions:-Xms256m -Xmx256m -XX:+PrintGCDetails -Xms: 设置初始分配大小,默认为物理内存的 1/64 -Xmx:最大分配内存,默认为物理内存的1/4 -XX:printGCDetails:输出详细的gc处理日志 public class HeapDemo { public static void main(String[] agrs){ long maxMemory=Runtime.getRuntime().maxMemory(); long totalMemory=Runtime.getRuntime().totalMemory(); System.out.println("maxMemory="+maxMemory+"字节,"+(maxMemory/(double)1024/1024)+"MB"); System.out.println("totalMemory="+totalMemory+"字节,"+(totalMemory/(double)1024/1024)+"MB"); } }