JVM(一)

宋红康GC134-195

基础信息:魔数,字节码文件对应的java版本号,访问表示public final以及父类和接口

常量池:保存了字符串常量,类或者是接口名,字段名,主要在接口中使用

字段:当前类或者是接口声明的字段信息

方法:当前类或者接口声明的方法信息,字节码指令

属性:指的是类的属性,源码的文件名以及类的列表

一)JVM是如何运行的?

1)在程序运行前先将JAVA代码转化成字节码文件也就是class文件,JVM需要通过类加载器将字节码以一定的方式加载到JVM的内存运行时数据区将类的信息打包分块填充在运行时数据区;

2)但是字节码文件是JVM的一套指令运行规范,并不能直接交给底层的操作系统来执行,因此需要特殊的命令解析器,也就是JVM的执行引擎会将字节码翻译成底层的操作系统指令也就是0 1的二进制操作系统指令数据交给CPU执行,因为操作系统只认机器码,不认识字节码

3)执行引擎在进行执行的过程中也会调用其它语言的接口,比如说调用本地库接口调用本地方法来实现整个程序的运行;

4)JVM=类加载器+运行时数据区+执行引擎+本地库接口

类加载器:加载class字节玛的内容到内存中

运行时数据区:负责管理JVM使用到的内存,比如说创建对象和销毁对象

执行引擎:将字节码文件中的内容解析成机器码,同时使用即时编译优化性能

本地方法接口:调用本地已经编译的方法,比如说虚拟机中已经提供好的C/C++的方法

二)JVM的内存布局+JVM的运行时数据区+Java的内存布局

<<java虚拟机规范>>白皮书是给JVM开发厂商去看的,指导开发厂商实现JVM,默认的JVM是hotSpot

1)程序计数器 :当前线程执行的字节码指令的地址,CPU的个数有限,但是任务很多,CPU会频繁进行线程切换,某一块程序会一直经历执行,暂停,再继续执行,就需要有个东西来记录当前线程执行到哪一步,用于存储当前线程执行的执行的字节码的指令的地址,在多线程环境下,程序计数器用于实现线程切换,保证线程恢复执行的时候能够继续从正确的位置开始执行代码

**2)JAVA虚拟机栈:用于存储JAVA方法调用和局部变量(方法内部调用的变量),**局部变量的生命周期是和方法的生命周期是一模一样的,当方法执行完成,方法调用出栈,局部变量也会销毁,为什么JAVA虚拟机栈也是线程私有的呢?因为线程执行方法的局部变量只会有线程本身使用,当前线程执行方法的局部变量,其他线程是不会使用到这个变量,使用到这个方法

**3)本地方法栈:**字符串常量池的底层实现是依靠C++的map来实现的,C++的hashmap也是需要存放局部变量的,存放C++本地方法的方法调用和局部变量

4)堆:对象和数组

5)方法区:类的结构字段方法,静态变量常量,常量池,类里面有几个方法记录的是类原信息
JMM:一种内存模型,为了提升CPU的读写效率, 充分利用CPU资源

三)堆和栈有什么区别?

1)存放的数据内容不同

2)大小不同

3)访问数据性能不同:因为堆很大,进行查询对象的时候需要进行寻址和内存管理 ,但是栈存放基本数据类型,内存固定,不需要有动态数据的变化,不需要进行访问,再多大部分情况下,从栈上面寻找数据是很快的,不需要寻址和内存管理

4)功能侧重点不同 :堆是JAVA虚拟机的主要存储单位,JAVA中的对象和数组都是保存在这个区域的,而栈式JAVA虚拟机基本的运行单位,也就是说,堆主要解决的是数据的存储,数据怎么放,放在哪里的问题,但是栈主要解决的是JVM程序运行的调用关系;

四)方法区和永久代有什么区别?

方法区是JAVA虚拟机规范时候给的一个概念,包括JAVA虚拟机的运行时数据区

但是Hotspot针对于方法区的实现给出了不同的名称

JDK1.7永久代=方法区实现,但是JDK1.8元空间=方法区实现

方法区是定义的名称,但是永久代和元空间都是方法区的实现而已

五)JDK1.8方法区有什么优化?

1)将元空间改成了直接内存

2)将字符串常量池移动到了堆上

在JAVA开发中最常用的两个类型就是对象和String类型,字符串常量池比较大,最大的地方就要放在运行数据区的堆空间上

六)字符串常量池是怎么实现的?

谈谈对Java中符号引用和引用的理解 - 知乎 (zhihu.com)

直接引用:根据内存地址可以直接拿到对象的引用,直接可以定位到字面量的引用地址

符号引用:直接进行编译,还没有进行类加载,就是一个占位符,标记着内存的一个位置

字面量:实际的字符串,判断字符串常量池是否存在该字符串的依据,如果key存在,那么直接就把value值赋值给实际的引用,如果没有就现存

从HotSpot虚拟机来说,字符串常量池是依靠C++的HashMap来实现的,key是字符串常量的字面量,value是字符串对象的引用

编译期常量池:在编译期间可以确定的常量

运行期常量池:在运行期间可以确定的常量,String的intern()方法,将动态生成的东西就是放在运行期常量池的
1)严重性:内存溢出>内存泄漏: 比如说ThreadLocal没有调用remove

2)内存泄漏最终会导致内存溢出,而内存溢出可能是内存泄漏导致的,比如说网络IO未释放资源
类加载的过程?==类的声明周期

从下向上甩锅,从上向下查询

Serial和Serial old单线程垃圾回收器

ParNew针对于单线程的升级版本是多线程的垃圾回收器:

Parallel Scavenge/Parallel Old:吞吐量优先的垃圾回收期,以回收内存为主,速度比较低,这个垃圾回收器只是保证了吞吐量,但是实际程序是让用户有最少的等待时间

CMS:垃圾回收器可以保证最小的等待时间,就是快,不影响用户久等,不需要将垃圾全部清除掉,多进行几次GC不就行了嘛,需要手动指定

为什么CMS和ParNEW不能一起用,设计理念不同

G1:可控垃圾回收时间的垃圾回收器(JDK 9以后HotSpot默认的垃圾的回收器)

分成多个区,为什么分区算法是可控的?因为分区算法里面有很多区,再进行垃圾回收的时候,假设一共有4个区,他不会保证在这一次GC将A B C D四个区域的垃圾全部回收,而是保证的是可控时间,但是会保证时间到了就罢工,如果时间允许的话,G1垃圾回收器会多回收几个区域,如果时间不允许,我少干一点活,到点就下班;

分代算法为什么时间不可控?

ZGC:停顿时间极短,不超过10ms情况下尽量提高垃圾回收吞吐量的垃圾回收器

相关推荐
一键三联啊1 小时前
GC的查看
java·jvm·python
头顶秃成一缕光4 小时前
JVM快速入门
java·linux·jvm·ide·spring·spring cloud·servlet
Normal Developer10 小时前
HotSpot的算法细节
java·jvm·算法
柯34912 小时前
JVM-类加载机制
java·开发语言·jvm
风雨无阻fywz12 小时前
java 类的实例化过程,其中的相关顺序 包括有继承的子类等复杂情况,静态成员变量的初始化顺序,这其中jvm在干什么
java·开发语言·jvm
lsnm16 小时前
【LINUX操作系统】线程操作
linux·jvm·c++·ubuntu·centos·gnu
碎梦归途19 小时前
23种设计模式-行为型模式之中介者模式(Java版本)
java·jvm·设计模式·中介者模式·软件设计师
backRoads20 小时前
JVM模型、GC、OOM定位
jvm
小红的布丁20 小时前
JVM 内存分配策略
java·jvm
backRoads20 小时前
JVM GC垃圾回收算法
jvm