JVM基础
简介
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
- 常见的JVM实现
- Hotspot
oracle官方,我们做实验用的JVM。 - Jrockit
BEA,曾经号称世界上最快的JVM;被Oracle收购,合并于hotspot。 - TaobaoVM
hotspot深度定制版。 - LiquidVM
直接针对硬件。 - azul zing
最新垃圾回收的业界标杆,需要收费。
- Hotspot
javac
简介
Javac是一种编译器,将一种语言转换为另一种语言规范。编译器的作用就是将符合java语言规范的源代码转化为JVM虚拟机能够识别的字节码文件的过程。
对于java而言。javac任务就是将java源代码转换为jvm能够识别的二进制码。将.java文件转换为.class文件,这些.class文件也就是字节码文件只有JVM能够识别。
编译过程原理
java从编码到执行
JDK,JRE,JRM区别
- JDK
Java Development Kit.简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境。SDK是Software Development Kit 一般指软件开发包,可以包括函数库、编译程序等。 - JRE
JRE是Java Runtime Enviroment是指Java的运行环境,是面向Java程序的使用者,而不是开发者。 - JVM
Java Virtual Machine就是我们常说的java虚拟机,它是整个java实现跨平台的最核心的 部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是 经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。
java Dynamic Linking(动态链接)
- 栈帧组成
局部变量表,操作数栈,动态链接 - java动态链接
动态链接是一个将符号引用解析为直接引用的过程。java虚拟机执行字节码时,遇到一个操作码,操作码第一次使用一个指向另一类的符号引用,则虚拟机就必须解析这个符号引用。- 解析时需要执行三个基本的任务:
- 查找被引用的类(有必要的话就装载它,一般采用延时装载)。
- 将符号引用替换为直接引用,这样当再次遇到相同的引用时,可以使用这个直接引用,省去再次解析的步骤。
- 当java虚拟机解析一个符号引用时,class文件检查器的第四趟扫描确保了这个引用时合法的。
- 解析时需要执行三个基本的任务:
内存模型
JAVA分为 栈、堆(新生代+老年代)、方法区
- 程序计数器(Program Counter Register)
当前线程所执行的字节码的行号 指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的 字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个 计数器来完成。 - 栈
栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈。 - 堆
堆由开发人员进行设置,有默认大小设置,JAVA程序中JVM进行自动回收。 - 方法区(Method Area)
方法区是被所有线程共享。
所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。
简单说,所有定义的方法的信息都保存在该区域,此区属于共享区间。
静态变量、常量、类信息(构造方法/接口定义) 、运行时常量池存在方法区中 。
但是实例变量 存在堆内存中,和方法区无关。
新生区(New/Young Generation)
新生代(Young Generation),常称为YoungGen,位于堆空间;
新生区 又分为 Eden区 和 Survior(幸存区)。
Eden : 新创建的对象
Survior 0、1:经过垃圾回收,但是垃圾回收次数小于15次的对象
老年代(Old Generation)
老年代(Old Generation),常称为OldGen,位于堆空间;
Old : 垃圾回收次数超过15次,依然存活的对象
验证堆和方法区不位于同一内存中参数 -Xmx180m -Xms180m -Xmn90m -XX:MetaspaceSize=170m -XX:MaxMetaspaceSize=170m -XX:+PrintGCDetails
在JDK小于1.8的版本中字符串位于PermGen space(永久区,即方法区),1.8(包括)之后,位于堆中
JVM中内存相关参数
-Xms Java堆内存初始大小
-Xmx Java堆内存最大大小
-Xmn Java堆内存中的新生代大小,扣除它就是老年代大小
-XX:PermSize(1.8之后:-XX:MetaspaceSize) 永久代初始大小
-XX:MaxPerSize(1.8之后:-XX:MaxMetaspaceSize) 永久代最大大小
-Xss 每个线程的栈内存大小
注:通常情况下,Xms和Xmx,-XX:PermSize和-XX:MaxPerSize都会设置为一样。
-XX:MaxTenuringThreshold 多少岁进入老年代-默认15
-XX:PretenureSizeThreshold 超过多少字节的大对象直接进入老年代
-XX:HandlePromotionFailure MinorGC时,如果老年代剩余空间小于新生代对象总大小,但是如果大于之前平均进入老年代对象的大小,是否尝试进行MinorGC(默认开启)
-XX:SurvivorRatio=8 Eden区的比例
-XX:+UseParNewGC 指定使用ParNewGC垃圾回收器
-XX:ParallelGCThreads,指定ParNewGC线程数量,一般不指定ParNewGC会自动根据CPU核数适配
-XX:+PrintGCDetails 打印GC详细日志
其他
- 使用JDK安装包安装JDK时,电脑会同时安装两套JRE,位于JDK中的这一套是运行我们开发时的普通程序,而另外的一套是运行生产环境的程序,这是因为JDK安装时自动在系统环境变量的path填充有“%SystemRoot%system32;%SystemRoot%;”参数,指向Windows/system32目录下的java.exe。
- CA FE BA BE代表这是一个class文件
参考
https://www.cnblogs.com/williamjie/p/9558094.html;
https://blog.csdn.net/u010393809/article/details/53169255;
https://blog.csdn.net/WTUDAN/article/details/104526344?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_utm_term~default-1.pc_relevant_default&spm=1001.2101.3001.4242.2&utm_relevant_index=4;
https://www.jianshu.com/p/8abf92faa9ad;https://blog.csdn.net/chuobenggu7592/article/details/100978957;https://blog.csdn.net/K346K346/article/details/80849966?spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-2defaultOPENSEARCHRate-2.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-2defaultOPENSEARCHRate-2.nonecase