java虚拟机入门
1、jvm的位置
jvm位于操作系统和java程序之间,并且JVM执行字节码时实际上还是要解释成具体操作平台的机器指令的。
通过JVM,Java实现了平台无关性,Java语言在不同平台运行时不需要重新编译,只需要在该平台上部署JVM就可以了。因而能实现一次编译多处运行。
2、jvm的体系结构
每执行一个方法栈就要出栈,如果在栈区域有垃圾,将会造成程序堵塞,jvm调优主要是发生在堆和方法区
方法区在JDK1.8及之后变为元空间
3、类加载器
作用:加载Class文件
加载器的类型
1.虚拟机自带的加载器
2.启动类(根)加载器
3.扩展类加载器
4.应用程序加载器(当前应用的加载器)
双亲委派机制 :安全
APP-->EXC-->BOOT :如果ROOT有该class文件,将会首先加载ROOT,如果没有则看EXC以此类推
双亲委派机制得工作过程:
1-类加载器收到类加载的请求;
2-把这个请求委托给父加载器去完成,一直向上委托,直到启动类加载器;
3-启动器加载器检查能不能加载(使用findClass()方法),能就加载(结束);否则,抛出异常,通知子加载器进行加载。
4-重复步骤三
沙箱安全机制
Java安全模型的核心就是Java沙箱,什么是沙箱?沙箱是一个限制程序运行的环境。通过沙箱安全机制,使得java程序比较安全。
4、Native
编写一个多线程类启动
public class NativeDemo {
public static void main(String[] args) {
new Thread(()->{},"thread name").start();
}
}
点进start查看源码
private native void start0();
native
:凡事带了native关键字的,说明java的作业范围达不到了,会去调底层c语言的库会进入本地方法栈,调用本地方法接口JNI
JNI
:扩展java的使用内存区域专门开辟一块标记区域:Native Method Stack,登记Native方法,在执行引擎的时候加载本地库
native现在用的比较少,现在调其他接口可使用Socket、Webservice、http等
5、pc寄存器
PC寄存器( PC register ):每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。
PC寄存器里保存有当前正在执行的JVM指令的地址。 每一个线程都有它自己的PC寄存器,也是该线程启动时创建的。保存下一条将要执行的指令地址的寄存器是 :PC寄存器。PC寄存器的内容总是指向下一条将被执行指令的地址,这里的地址可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。
6、JVM 方法区(元空间)
方法区(jdk1.7后合并到了堆),HotSpot虚拟机在JDK1.7及之前版本将方法区称为永久代
JDK1.6之前,有永久代,常量池在方法区
JDK1.7常量池放入堆
JDK1.8之后,无永久代,常量池在元空间
元空间和堆不相连,但和堆共享物理内存,逻辑上可以认为在堆中
方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。实例变量存放在堆内存,和方法区无关
7、栈
栈内存,主管程序的运行,生命周期和线程同步;
线程结束,栈内存就会释放,对于栈来说不存在垃圾回收的问题
一旦线程结束,栈的空间也释放
栈
:8大基本数据类型 + 对象引用 + 实例方法 + 属性参数
8、堆
首先在伊甸区放不下之后会移到幸存区1以此往右推知道老年代,最后老年代满了之后就会出现堆溢出
一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域,他存放所有的实例对象
Java堆在JVM启动时被创建,其空间大小也就被确定了。可使用**-Xmx**(最大)、-Xms(最小)调节堆大小
gc垃圾收集器的主要管理区域,可分为新生代(1/3)和老年代(2/3)
新生代可惜分为Eden、Survivor (From) 、Survivor (To) = 8:1:1
(最大)、-Xms(最小)调节堆大小
gc垃圾收集器的主要管理区域,可分为新生代(1/3)和老年代(2/3)
新生代可惜分为Eden、Survivor (From) 、Survivor (To) = 8:1:1