初探JVM
简介
JVM(Java Virtual Machine)是Java虚拟机。Java虚拟机本质就是一个程序,当它在命令行上启动的时候,就开始执行保存在某字节码文件中的指令。Java语言的可移植性正是建立在Java虚拟机的基础上。任何平台只要装有针对该平台的Java虚拟机,字节码文件就可以在该平台上运行。也就是常说的“一次编译,多次运行”。
JVM位于操作系统之上,和软件同级。
JVM的体系结构
类加载器
虚拟机把描述类的数据从class字节码文件加载到内存,并对数据进行检验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。
类加载器整个完整的生命周期包括加载、验证、准备、解析、初始化、使用、卸载七个阶段。“家(加载)宴(验证)准(准备)备了西(解析)式(初始化)菜”
双亲委派机制
其具体的过程表现为当一个类加载的过程中,它不会去加载,而是委托给自己的父类去加载,父类又委托给自己的父类。所有的类加载都会委托给顶层的父类,即根启动器(Bootstrap Classloader)进行加载,然后父类自己无法完成这个加载请求,子加载器才会尝试自己去加载。
1、类加载器收到类加载的请求
2、将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
3、启动类加载器检查是否能加载当前这个类,如果能加载就结束,并使用当前的加载器,如果不能则抛出异常,通知子类加载器进行加载。
4、如果重复第3步骤没有加载,则报Class Not Found错误。
沙箱安全机制
Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。沙箱主要限制系统资源访问,那系统资源包括什么?——CPU、内存、文件系统、网络。不同级别的沙箱对这些资源访问的限制也可以不一样。
所有的Java程序运行都可以指定沙箱,可以定制安全策略。
Native当一个方法使用Native修饰,说明在Java的作用范围达不到了,需要调用底层C语言的库。
方法区static、final、class、常量池
栈溢出
public static void main(String[] args) {
ne Test.a();
}
public void a(){
b();
}
public void b(){
a();
}
方法在内存中的执行过程
堆
堆
GC垃圾回收机制,主要是回收新生区中的伊甸园区和养老区中不使用或丢弃的对象。
堆内存中细分为三部分
1、新生区类诞生和成长,甚至死亡的地方
伊甸园区所有的对象都是在伊甸园区诞生的
幸存者区(from、to)存放伊甸园区存活下来的对象(哪个区域为空,则是to)
2、老年区存放新生区存活下来的对象,不容易被清除。
3、永久区这个区域是常驻内存的。存储的是Java运行时的一些环境。这个区域不存在垃圾回收!关闭JVM虚拟机就会释放这个区域的内存。
jdk1.6之前叫永久代,常量池是在方法区;
jdk1.7叫永久代,慢慢的在退化。常量池在堆中;
jdk1.8之后叫元空间,常量池在元空间;
堆内存调优若报了OOM错误
1、尝试扩大堆内存,看结果(-Xms1024m -Xmx1024m -XX:PrintGCDetails)
2、分析内存,看是否存在死循环等问题
JProfiler工具分析OOM原因作用
1、分析Dump内存文件,快速定位内存泄漏
2、获得堆中数据
3、获得大的对象
安装与下载
1、IDEA中在setting中安装JProfiler插件
2、Java Profiler - JProfiler (ej-technologies.)到官网下载。
简单使用
1、在IDEA中添加 “-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError”
2、将生成的JProfiler文件在JProfiler中打开分析
GCGC的作用区域只有在堆和方法区中。
GC涉及的算法
1、复制算法划分俩个区域,每次只使用其中一个区域,垃圾回收时,把正在使用的对象放到另一个区域(主要使用在新生区)。
2、标记清除算法标记被引用的对象,清除未被标记的对象。
3、标记整理算法标记引用的对象,清除未被标记的对象并把标记的对象压缩到一个堆中。
内存效率 复制算法>标记清除算法>标记整理算法(时间复杂度)
内存整齐度复制算法==标记整理算法>标记清除算法
内存利用率标记整理算法==标记清除算法>复制算法