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情况下尽量提高垃圾回收吞吐量的垃圾回收器

相关推荐
jmxwzy9 分钟前
JVM(java虚拟机)
jvm
Maỿbe36 分钟前
JVM中的类加载&&Minor GC与Full GC
jvm
人道领域2 小时前
【零基础学java】(等待唤醒机制,线程池补充)
java·开发语言·jvm
小突突突2 小时前
浅谈JVM
jvm
饺子大魔王的男人3 小时前
远程调试总碰壁?局域网成 “绊脚石”?Remote JVM Debug与cpolar的合作让效率飙升
网络·jvm
天“码”行空13 小时前
java面向对象的三大特性之一多态
java·开发语言·jvm
独自破碎E19 小时前
JVM的内存区域是怎么划分的?
jvm
期待のcode20 小时前
认识Java虚拟机
java·开发语言·jvm
leaves falling1 天前
一篇文章深入理解指针
jvm
linweidong1 天前
C++ 中避免悬挂引用的企业策略有哪些?
java·jvm·c++