1、JVM的位置:JVM是在操作系统上面的应用软件
JVM虚拟机有三种如下:
① Sun公司的HotSpot;
② BEA公司的JRockit;
③ IBM公司的J9 JVM;
java虚拟机属于第一种:
2、JVM的体系结构:
3、类加载器
作用:加载class文件 -------(类是模板,对象是具体的)
简单执行过程:
双亲委派机制:
定义:在程序运行时某个类加载器需要加载某个.class
文件时,它首先把这个任务委托给他的上级类加载器(即ExtClassLoader),ExtClassLoader加载器在把任务委托给他的上级类BootstrapClassLoader,如果BootstrapClassLoader没有加载就到ExtClassLoader加载,如果ExtClassLoader没有加载就自己加载,按照这个递归这个操作,来完成加载该文件的机制就称为双亲委派机制
类加载器的类别:
(1)BootstrapClassLoader(启动类加载器)
它是由C++写的,加载java核心库-->java.*;java/lib目录下的jar,自己复制进去也会加载,但是java环境会被不坏
(2)ExtClassLoader(标准扩展类加载器)
它是由java写的,加载扩展库即java/lib/ext目录下的jar,java.ext.dir
指定位置中的类,开发者可以直接使用标准扩展类加载器。
(3)AppClassLoader(系统类加载器)
它是由java写的,加载程序所在的目录,我们自己写的类大多数使用这个如user.dir
所在的位置的class
(4)CustomClassLoader(用户自定义类加载器)
它是由java写的,用户自定义的类加载器,可加载指定路径的class
文件,Tomcat实现就是有自己的加载器
双亲委派机制的作用:
1)、防止加载相同的class文件,保证数据的安全
2)、防止核心类被破坏,造成java环境的污染
4、沙箱安全机制
防止远程代码(病毒)入侵
5、native
凡是带native关键字的,说明java的作用范围达不到了,只能调用C语言的库;会进入本地方法栈;然后会调用本地接口(JNI),JNI作用:扩展java的使用,融合不同的语言为java所用;最初的C、C++,它在内存区域中专门打开调了一块标志区域:本地方法栈,登记native方法
例子:源码:Thread的类中的----》private native void start0();
6、PC寄存器
1)、PC寄存器( PC register ):每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。PC寄存器里保存有当前正在执行的JVM指令的地址。 每一个线程都有它自己的PC寄存器,也是该线程启动时创建的。保存下一条将要执行的指令地址的寄存器是 :PC寄存器。PC寄存器的内容总是指向下一条将被执行指令的地址,这里的地址可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。
2)、每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。
3)、这块内存区域很小,它是当前线程所执行的字节码的行号指示器,字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令。
4)、如果执行的是一个Native方法,那这个计数器是空的。
7、方法区:
方法区(Method Area)与 Java 堆一样,是所有线程共享的内存区域。
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中和方法区无关
8、栈:(先进后出、后进先出)数据结构
定义:栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
程序=数据结构+算法
程序执行方法,就是靠栈来调用,最先把main()方法压在栈的底部,其它方法在上面,等到main()出栈程序执行也就结束了。
所以栈是不存在垃圾回收问题
9、堆
Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的
类加载器读取了类文件后,一般会把类、方法、常量、变量,保存我们所有引用类型的真实对象
堆内存中分成三个区域:
1)、新生区(伊甸区)
2)、养老区
3)、永久存储区
所有GC垃圾回收是在堆里的伊甸区和养老区
jdk8后把永久区名称改为元空间
新生区:
类:诞生和成长的地方,甚至死亡
伊甸区:所有对象都是在这里new出来的,即实例化
幸存区(0 1):
养老区:
永久区:这个区域常驻内存的,用来存放携带的class对象,interface元数据,存储的是java运行时的一些环境或类信息,这个区域不存在垃圾回收
jdk1.6:永久代、常量池在方法区
jdk1.7:永久代、但是慢慢的退化,常量池在堆中
jdk1.8之后:无永久代、常量池在元空间
OOM定义:OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError。看下关于的官方说明: Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector. 意思就是说,当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error(注:非exception,因为这个问题已经严重到不足以被应用处理)。
遇到OOM问题:
参考:https://www.cnblogs.com/zhoading/p/10249302.html
(1)调堆内存大小;
修改堆的大小:
说明:
-Xms:20M 初始化堆内存大小
-Xmn:20M 堆内存最大值
-Mmn:10M 新生代内存设置
-XX:+PrintGcDetails 用于打印GC的日志信息
-verbose:gc 用于查看Java垃圾收集的结果
idea界面:
(2)分析内存
分析堆内存工具:MAT(eclipse)、Jprofiler(idea)
MAT、Jprofiler作用:快速分析Dump内存文件,快速定位内存泄漏
VM参数:https://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html
要在idea安装插件Jprofiler
(1)安装:https://www.cnblogs.com/javabg/p/11499098.html
(2)使用:https://segmentfault.com/a/1190000021881331
10、GC(垃圾回收)
GC的作用区域:方法区,堆
JVM在进行GC时,并不是三个统一回收,大部分时候,回收新时代
年轻代:存活率低-》复制算法
幸存区(form,to------》谁空谁是to)
老年区:存活率大-》标记清除算法(内存碎片不是太多)、标记压缩混合实现
GC两种类:轻GC(普通的GC)、重GC(全局GC)
GC的算法:标记清除法、标记整理、复制算法、引用计数法
参考:https://blog.csdn.net/qq_21383435/article/details/80473540
总结:
内存效率:复制算法>标记清除算法>标记压缩算法
内存整齐度:复制算法=标记压缩算法>标记清除算法
内存利用率:标记清除算法=标记压缩算法>复制算法
11、举例
(1)JMM(java Memory Model)-》Java内存模型
1)定义:(java Memory Model)-》Java内存模型
2)作用:缓存一致性协议,用于定义数据读写的规则(遵循)
参考:https://blog.csdn.net/zjcjava/article/details/78406330
3)如何学习?
面试题:https://www.cnblogs.com/wjh123/p/11094622.html