当前位置: 首页 > web >正文

JVM故障处理与类加载全解析

1、故障处理工具

基础故障处理工具
jps:
可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(LVMID,Local Virtual Machine Identifier)
jstat:
jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具
jinfo:
jinfo(Configuration Info for Java)的作用是实时查看和调整虚拟机各项参数,windos使用该命令会受到限制
jmap:
jmap(Memory Map for Java)命令用于生成堆转储快照,jinfo命令一样,jmap有部分功能在Windows平台下是受限的
jhat:
JDK提供jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照。可以通过HTTP界面可视化
.java文件不可以直接被jhat分析我们需要先调用以下代码,转换文件格式
jstack:
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。

2、类文件结构

class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在文件之中,中间没有添加任何分隔符。
魔数和版本号
        Class文件的魔数是确定这个文件是否为一个能被虚拟机接收的Class文件——取值为0xCAFEBABE
        版本号分为主版本号和次版本号,高版本可以向下兼容低版本。虚拟机完全拒绝执行超过其版本号的Class文件
常量池
        常量池存储:字面量和符号引用。常量池的每一个常量都是一个表
访问标志
        这个标志用于识别一些类或接口层次的访问信息。
类索引、父类索引、接口索引集合
        class文件中有这三项数据来确定该类型的继承关系
字段表集合
        用于描述接口或类中声明的变量
方法表集合
属性表集合

3、类加载

类加载:JVM把类的数据从Class文件加载到内容,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型
类加载的时机
类的生命周期可以被定义为以下七个过程
加载——验证——准备——初始化——卸载顺序是确定的
有且仅有六种情况需要进行初始化(主动引用
  1. 遇到 new、getstatic、putstatic 或 invokestatic 这四条字节码指令时
  • 典型场景:使用 new 关键字实例化对象、读取或设置一个类的静态字段(被 final 修饰、已在编译期把结果放入常量池的静态字段除外)、调用一个类的静态方法
  1. 使用 java.lang.reflect 包的方法对类进行反射调用的时候
  2. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
  3. 当虚拟机启动时,用户需要指定一个要执行的主类(包含 main () 方法的那个类),虚拟机会先初始化这个主类
  4. 当使用 JDK 7 新加入的动态语言支持时
  5. 当一个接口中定义了 JDK 8 新加入的默认方法(被 default 关键字修饰的接口方法)时,如果有这个接口的实现类发生了初始化,该接口要在其之前被初始化
除此之外,所有引用类型的方式都不会触发初始化,称为被动引用。
给个例子
package org.fenixsoft.classloading;
/*** 被动使用类字段演示一:* 通过子类引用父类的静态字段,不会导致子类初始化**/
public class SuperClass {static {System.out.println("SuperClass init!");}public static int value = 123;
}
public class SubClass extends SuperClass {static {System.out.println("SubClass init!");}}
/*** 非主动使用类字段演示**/
public class NotInitialization {public static void main(String[] args) {System.out.println(SubClass.value);}
}
        上述代码运行之后,只会输出“SuperClass init!”,而不会输出“SubClass init!”。对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
类的加载过程
加载、验证、准备、解析、初始化
加载过程
        通过类的全限定名获得字节流
        将字节流(静态)转换为方法区的运行时数据结构
        在内存生成该对象作为方法区这个类的访问接口
验证
        目的是确保Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求。保证这些能正确地存储到方法区。
文件格式验证:保证输入的字节流能正确地解析并存储于方法区之内
元数据验证
字节码验证
符号引用验证
准备
只准备空间,这里的 初始值默认赋该类型的零值,若类变量被 final 修饰且为基本类型或字符串,则会在准备阶段初始化为指定值,静态常量直接赋值
解析
把符号引用直接转为直接引用的过程
初始化
把准备阶段赋的0值,转换为实际数据
使用
卸载
类加载器
        任意一个类,都必须由加载它的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性,换句话说只有同一个类加载器加载出来的两个相同的类才相等。
类加载器分类
  • 启动类加载器Bootstrap ClassLoader:加载固定路径下,固定JRE/lib下的核心类库(如rt.jar)
  • 扩展类加载器Extension ClassLoader:加载JRE/lib/ext下的扩展类,是对Java语言的扩展
  • 应用程序类加载器Application ClassLoader:加载用户类路径(ClassPath)上的类
  • 自定义ClassLoader:用户自定义的类加载器
双亲委派模型
双亲委派
双亲委派模型的工作流程
        如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载
  • 类加载请求先委托父加载器处理
  • 父加载器无法完成时子加载器才尝试加载
优点:
  • 避免重复加载
  • 防止核心API被篡改
破坏双亲委派
破坏双亲委派,指的是类加载器在某些场景下不遵循 “先委托父类加载器” 的规则。例如:
Tomcat 的类加载器设计
        Tomcat 需要支持多个 Web 应用隔离(同一类在不同应用中可加载不同版本),因此其类加载器结构也破坏了双亲委派。
Tomcat 的类加载顺序(以 WebAppClassLoader 为例):
  1. 先加载 Web 应用的/WEB-INF/classes目录下的类;
  2. 再加载/WEB-INF/lib目录下的 JAR 包;
  3. 最后才委托父类加载器(Common ClassLoader)加载。
http://www.xdnf.cn/news/15233.html

相关文章:

  • ✨ FastMCP 实战进阶:构建可远程访问的 MCP 工具服务与客户端(Python 深度解析)
  • Elasticsearch混合搜索深度解析(上):问题发现与源码探索
  • 【flutter】flutter网易云信令 + im + 声网rtm从0实现通话视频文字聊天的踩坑
  • 影石(insta360)GO3拇指相机格式化后的恢复方法
  • OpenCV 与深度学习:从图像分类到目标检测技术
  • 如何安装和配置Autoptimize插件以提高WordPress网站访问速度
  • 飞算JavaAI:重塑Java开发的“人机协同“新模式
  • 免费应用分发平台的安全漏洞和防护机制是什么?
  • Jenkins 自动触发执行的配置
  • 飞算JavaAI:重构Java开发的“人机协同”新范式
  • JavaScript VMP (Virtual Machine Protection) 分析与调试
  • 创建显示心电图的组件
  • 前端学习4:小白入门注册表单的制作(包括详细思考CSS、JS实现过程)
  • uniapp语音播报天气预报微信小程序
  • 格密码--数学基础--02基变换、幺模矩阵与 Hermite 标准形
  • 从UI设计到数字孪生实战应用:构建智慧金融的风险评估与预警平台
  • 使用 SSH 连接 GitHub
  • 飞算 JavaAI 深度体验:开启 Java 开发智能化新纪元
  • 速学 RocketMQ
  • 基于定制开发开源AI智能名片与S2B2C商城小程序的旅游日志创新应用研究
  • FPGA实现SDI转LVDS视频发送,基于GTX+OSERDES2原语架构,提供2套工程源码和技术支持
  • Maui劝退:用windows直接真机调试iOS,无须和Mac配对
  • leetcode:518. 零钱兑换 II[完全背包]
  • Python 类型注解实战:`Optional` 与安全数据处理的艺术
  • 静态路由综合实验
  • GitHub敏感信息收集与防御指南
  • 人大金仓下载安装教程总结
  • 时间显示 蓝桥云课Java
  • 安卓应用启动崩溃的问题排查记录
  • P1722 矩阵 II 题解 DFS深度优先遍历与卡特兰数(Catalan number)解