讲诉JVM

jvm是Java代码运行的环境,他将java程序翻译成为机器可以可以识别的机器码,可以跨平台运行如linuc或者windos

简单说一下我对jvm运行的理解,

首先我们运行程序的时候,类加载器会将类按需加载到元空间/方法区 里面

然后启动线程的时候,jvm就会给每个线程分配一个独立的 ,如果有native方法就会有一个本地方法栈 ,对应的每个线程会有一个 程序计数器 用于记录线程运行状态的,线程运行到每一个方法就会有一个栈帧 ,方法执行完, 栈帧就会被释放,后进先出,当线程运行完成,栈也就释放了

在线程运行过程中,所新建和操作的一下临时对象就就会在中创建然后被引用,当线程执行完成,没有引用的对象,在下一次垃圾回收执行的时候被清理。大体流程就是这样

类的加载 触发:是按需要加载的,当被new到,静态方法或静态成员被访问到,反射操作等就会触发类的加载,

类的加载过程:加载,连接,初始化,使用,销毁

加载 阶段:工具类名将类的字节码通过文件、网络等方式读取到内存中,然后解析加载到方法区/元空间中。

加载阶段完成之后就到连接

连接分为3个步骤,首先是验证,验证字节码结构,语义是否复java约束规范 例如开头是否 cafe babe,验证通过就到准备阶段,给静态变量分配内存,给初始值,常量赋值等

最后是解析阶段,将符合引用替换为直接引用,解析为直接内存地址,链接阶段就算完成了

最后就是初始化 了 ,静态变量初始值,执行静态快

初始化完成就是可以使用了,还有就是就是销毁,虽然这个销毁很少发生 在内存不足full GC的时候 还是有可能被销毁的

类加载过程是按双亲委派模型

因为类的加载器有 启动类加载器,扩展类加载器,应用类加载器,每个加载器各自负责加载不通的类,启动类加载java运行时环境所需的类 如string所在的lang包,list,map所在的util包,IO包等,扩展类加载器就是加载bin/ext目录下的第三方库。应用类加载器就是加载我们写的类的,所谓的双亲委派就是 一个类的加载器收到请求,会先去尝试让父类加载,向上委派,如果父类加载过就不需要再加载,例如应用类加载器收到请求 会委派给扩展类加载器,扩展类加载器又委派给启动类加载器,这样做的好处就是确保安全,避免核心类被加载,避免重复加载保证唯一。

类加载好了,在程序启动线程的适合,jvm就会给线程创建一个

这个栈是线程独有的,线程执行完,栈就会自动释放

在线程的运行过程中每执行到一个方法就会创建一个栈帧, 这个栈帧记录着方法执行的操作和数据。

栈帧保存的数据有,局部变量表操作数栈 (如果加减乘除的结果,操作完成就字符,先先进后出),还有动态链接 (方法内存地址,和引用),方法出口 (方法执行完成只有要干什么)

方法执行完栈帧也就出来了,他们后进先出的

线程运行过程程序计数器记录 着 线程的运行位置,在多线程情况下,上下文切换的适合让程序继续执行。

栈也会内存溢出 只是发生的比较少,还有一个深度不够的异常,就是线程执行的方法太深,如递归,不过这些发生的情况还是很少的。栈就大概这么了

线程的运行过程中 会产生很多的引用对象,这些读写被jvm分配到 中,

堆是jvm最大的一个区域,也是我们最关注的,问题也是最频繁的,处理不当就会产生内存溢出或内存泄漏,

首先是内存分配,对象被创建出jvm有几种内存分配方式

1指针碰撞 ,如果堆的内存充足而且规则连续,就会先数组移动指针一样分配,这个成为指针碰撞,这是简单,快速的

2空闲列表 :就是在内存不规则的情况下,jvm会维护一个空闲内存的列表,然后把对象分散的分配

空间的是否规则要看选用的什么类型的垃圾回收机制,有压缩整理功能的就会有规则的空间
++serial,parNew(没有压缩整理),CMS,G1(sweep)(没有)++

3 本地线程分配缓 存 简称TLAB ,就是给每个线程分配一个独立的堆空间用于,使用完自己的才去使用公共的。

对象的组成包含3部分,对象头,实例数据,补齐填充

对象头主要包含:自身运行的数据,hash码,GC分代年龄,锁状态标志,偏凉锁线程id等

实例数据:就是代码中各种成员变量

补齐填充:占位用的,就是为了补齐数 达到某个整数被,提高CPU的访问效率

堆被分新生代和老年,他们的占比默认是占1/3和2/3,

其中新生代又分为eden区和Survivor区,Survivor又分为s1和s2区,他们的默认比例8:1:1,

在垃圾回收的时候 会先把eden区的回收,然后把存活的对象放到s区,经过多次垃圾回收还存活的对象就会升等到老年区,只有在full gc的时候 老年区才会被回收

进入老年区的情况有以下几种,1就是到达阈值指定的,2到达阈值的大对象,3动态年龄判断,就是s区超过50%之后年龄大但却没有到阈值的,4老年代空间担保机制(每次mionr gc的时候都会先判断老年代剩余空间是否大于新生代的,如果大于就直接gc ,如果小于就会在判断 是否大于每次平均晋升值,如果小于就直接full gc,如果大于就minor gc ,如果值多就会直接放到老年代)

相关推荐
yuanbenshidiaos12 小时前
c++---------数据类型
java·jvm·c++
java1234_小锋15 小时前
JVM对象分配内存如何保证线程安全?
jvm
40岁的系统架构师18 小时前
1 JVM JDK JRE之间的区别以及使用字节码的好处
java·jvm·python
寻找沙漠的人19 小时前
理解JVM
java·jvm·java-ee
我叫啥都行19 小时前
计算机基础复习12.22
java·jvm·redis·后端·mysql
bufanjun0011 天前
JUC并发工具---ThreadLocal
java·jvm·面试·并发·并发基础
东阳马生架构1 天前
JVM简介—1.Java内存区域
jvm
工程师老罗1 天前
Android笔试面试题AI答之SQLite(2)
android·jvm·sqlite
Qzer_4072 天前
jvm字节码中方法的结构
jvm
奇偶变不变2 天前
RTOS之事件集
java·linux·jvm·单片机·算法