Java虚拟机机制
2024-03-05 12:32:29 14 举报
Java虚拟机(JVM)是Java技术的核心组成部分,它实现了Java语言的跨平台特性。JVM是一个虚拟的计算机,它负责将Java字节码翻译成特定平台的机器指令执行。这种翻译过程是在运行时进行的,因此Java程序可以在任何支持JVM的平台上运行,无需针对特定平台进行重新编译。JVM还提供了内存管理、垃圾回收等服务,确保了Java程序的稳定性和高效性。此外,JVM还包含了许多安全特性,如类加载机制、异常处理等,为Java程序提供了良好的安全性。总之,Java虚拟机是实现Java跨平台运行的关键,它为Java程序员提供了一个稳定、高效的运行环境。
作者其他创作
大纲/内容
方法区
JVM调优参数
3、ApplicationClassLoader: 负责将系统环境变量classpath、-cp和系统属性java.class.path指定的路径下的类库加载到内存。
1.jinfo pid,可以查看当前进行虚拟机的相关信息列举出来 2.jstat -gc pid ms,多长毫秒打印一次gc信息,打印信息如下,里面包含gc测试,年轻代/老年带gc信息等 3.jmap -histo pid | head -20,查找当前进程堆中的对象信息,加上管道符后面的信息以后,代表查询对象数量最多的20个font color=\"#4d4d4d\
JVM中的程序计数寄存器(Program Counter Register)中,Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。这里并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更加贴切(也称为程序钩子),并且也不容易引起一些不必要的误会。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。PC寄存器用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令。程序计数器它是一块很小的内存空间,几乎可以忽略不记。也是运行速度最快的存储区域。在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的Java方法的JVM指令地址;或者,如果是在执行native方法,则是未指定值(undefined)。它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。它是唯一一个在Java虚拟机规范中没有规定任何OutofMemoryError情况的区域。
①函数的局部变量表②操作数栈(计算中间结果)③函数的参数④帧数据
元数据区
程序计数器(pc寄存器)
老年代(2/3)
栈帧4
2、ExtensionClassLoader: 负责将<JAVA_HOME >/lib/ext目录或者由系统变量-Djava.ext.dir指定的目录中的类库加载到内存中。
JVM 虚拟机
栈帧2
Java栈帧
当前函数执行完后栈帧从Java栈中弹出
执行引擎
栈上分配
Java堆
常量池中的指针
栈帧1
每一个java线程中都会独立开辟的内存空间,随线程生命结束而回收
方法1
垃圾回收器
本地方法栈
java编译器
Java方法区
Eden区占比=8/10
双亲委派机制
Arthas-alibaba线上JVM监控诊断利器
类加载器 ClassLoader
.java文件
ToSuvivor=1/10
方法5
先进后出
保存异常处理表数据
程序计数器
垃圾回收器-GC( 1.8开始使用分代清理算法)
保存对象实例信息存放对象和数组信息
Java栈
线程一结束 该栈就释放
需求:1、有没有一个全局JVM运行时监控 ? CPU,线程,内存,堆栈信息等等2、CPU飙高,是什么造成的?3、接口没反应、卡住了,是不是死锁了 ?4、CTO说你们这个接口太慢了,要优化一下? 如何准确找出耗时的代码5、我写的代码没有执行,是部署的分支不对,还是我压根没提交?6、线上有一个低级错误,改起来很简单,能不能在不重启应用的情况下,进行类替换,热部署。
局部变量方法调用信息
主要功能:是支持方法调用和递归
===========JVM监测=============// -- thread id; thread -n 3; 查看进程信息//-- jad 查看反编译代码//-- watch 让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。 // --trace 【方法】内部调用路径,并输出方法路径上的每个节点上耗时;trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。 //-- stack 输出当前【方法】被调用的调用路径 //-- monitor 【方法】执行监控===========开发中助手=============《时空隧道》:监测过往请求中的参数及请求执行情况//-- tt -t 包名.类名 方法名; 监测当前请求//-- tt -i 1000; 查看id为1000的请求参数//-- tt -i 1000 -p; 查看并重新执行id为1000的请求《热力图》--必须在linux/mac设备上使用//-- profiler start//-- Started [cpu] profiling//-- span style=\
方法4
常量池的访问处理
线程私有栈(内存空间)
栈帧5
Survivor的存在意义,就是减少被送到老年代的对象进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。
执行java字节码
栈帧3
Eden和FromSuvivor中对象MinorGC一次后任然存活则迁移至toSuvivor中;
在多层次的java类加载器体系中,双亲委派机制是Java中的类加载机制,子类加载器会将其加载请求委派给父类加载器,只有在父类加载器无法加载该类时,子类加载器才会尝试加载。沙箱安全机制:比如自己写的String.class类不会被加载,这样可以防止核心库被随意篡改避免类的重复加载:当父ClassLoader已经加载了该类的时候,就不需要子ClassLoader再加载一次
方法3
.class文件
1.类型信息和类静态变量都保存在方法区中,常量池也存放于方法区中,2.程序中所有的线程共享一个方法区,所以访问方法区的信息必须确保线程是安全的。3.如果有两个线程同时去加载一个类,那么只能有一个线程被允许去加载这个类,另一个必须等待。4.在程序运行时,方法区大小可变的,程序在运行时可以扩展。5.方法区也可以被垃圾回收,但条件非常严苛,必须在该类没有任何引用的情况下。
①保存系统信息②保存类的字段、方法列表、常量池需要指定大小,否则有可能会占用系统全部内存
(类信息和方法信息)
1、BootstrapClassLoader: 负责将<JAVA_HOME>/lib目录、-Xbootclasspath选项指定的目录和系统属性sun.boot.class.path指定的目录下的核心类库加载到内存中。
就是一个指针,指向方法区中的方法字节码
HotSpot VM中的所有垃圾收集器采用的都是分代收集算法,针对年轻代通常采用的是复制算法,老年代可以采用“标记-清除”或“标记-整理”算法。Serial收集器采用的是复制算法,而Serial Old收集器采用的是“标记-整理”算法。一、新生代:复制算法 由于系统中大部分对象的生命周期非常短暂,所以并不需要按照1:1的比例来划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间(即From Survivor空间和To Survivor空间),每次使用Eden和From Survivor空间。当回收时,将Eden和FromSurvivor空间中还存活的对象一次性地复制到To Survivor空间,最后清理Eden和From Survivor空间。HotSpot VM默认Eden:Survivor为8:1,也就是每次新生代中可用内存空间为整个新生代容量的90%(其中一块Survivor不可用),只有10%的内存会被“浪费”。二、老年代:标记-清理(span style=\
登记native方法,在ExecutionEngine执行时加载本地方法库
线程私有
JVM 性能调优
①局部变量: 包括该方法中声明的变量、常量、基本数据类型和对象的引用等。②方法调用信息: 包括当前执行的方法的名称、方法参数、返回值等信息。
XX:MaxMetaspaceSize
方法2
FromSuvivor=1/10
新生代(1/3)
收藏
收藏
0 条评论
下一页