Java类加载机制及关于时序数据库IoTDB排查

排查时序数据库 IOTDB-4899 UDF develop UDF class with Enum, return 500 when querying - ASF JIRA 时,涉及的 Java 类加载机制知识如下:

一、类加载概述

类加载是指将类的.class文件中的二进制数据读入内存,并创建java.lang.Class对象的过程。该对象封装了类在方法区的数据结构,并提供访问接口。类加载器在预料类将被使用时,可预先加载,若.class文件缺失或错误,则在首次主动使用时报告LinkageError错误。

加载阶段,虚拟机需完成以下任务:

  1. 通过类的全限定名获取二进制字节流。
  2. 将字节流转换为方法区的运行时数据结构。
  3. 在Java堆中创建代表该类的java.lang.Class对象。

二、类加载机制

1. 双亲委派机制

双亲委派机制是指类加载器收到加载请求时,先委托给父加载器处理。请求依次向上传递,直至启动类加载器。若父加载器无法加载,子加载器才尝试加载。类加载器层次关系如下:

  • 启动类加载器 ‌:加载$JAVA_HOME\jre\lib下或-Xbootclasspath指定的类库(如rt.jar)。
  • 扩展类加载器 ‌:加载$JAVA_HOME\jre\lib\ext目录或由java.ext.dirs指定的类库。
  • 应用程序类加载器‌:加载用户类路径(ClassPath)指定的类。
  • 自定义类加载器‌:用于加载非标准Java类文件。

2. 缓存机制

缓存机制确保所有加载过的类被缓存。当需要使用类时,类加载器先从缓存区查找。修改类后,需重启JVM才能使修改生效。

三、问题排查

1. 问题背景

创建UDF(用户定义函数)成功,但执行时报错,找不到org.apache.iotdb.udf.MySum$1类。

2. 问题分析

2.1 org.apache.iotdb.udf.MySum$1类解析

该类名似匿名类。检查创建UDF的jar包,发现包含MySum$1类,但实际项目中只有MySum类。结合日志,报错位置在switch代码块,经查证,JVM在switch enum中case数量过多时,会编译出匿名类。

2.2 类加载器分析

结合类加载的全盘负责机制,匿名类由加载其依赖的org.apache.iotdb.MySum的类加载器A加载。A能成功加载org.apache.iotdb.udf.MySum,但无法加载org.apache.iotdb.udf.MySum$1。原因可能是A被关闭。

排查代码发现,使用try-with-resource语句自动关闭类加载器A,导致后续无法加载匿名类。

2.3 ClassLoader.close()方法分析

URLClassLoader在被close后无法加载新类或资源,但已加载的类和资源仍可访问。

2.4 setContextClassLoader方法分析

setContextClassLoader用于打破双亲委派机制。初步误以为是未正确设置ContextClassLoader导致问题,但经实验和查阅资料,确认应按全盘负责机制理解,setContextClassLoader不起作用。

3. 解决方案

  • 避免关闭类加载器‌:若可能,避免关闭用于加载UDF的类加载器,或确保在需要加载所有相关类后再关闭。
  • 优化代码结构‌:减少不必要的类加载器使用,优化代码结构,确保资源有效管理。

4. 类卸载时机

类满足以下条件时可能被卸载:

  • 类所有实例被回收。
  • 加载类的ClassLoader被回收。
  • 类对应的java.lang.Class对象无引用。

注意:ClassLoader不提供卸载类的接口,需等待JVM自动卸载。

相关推荐
这个DBA有点耶2 小时前
NULL不是空——数据库里最反直觉的设计,90%新人踩过的坑
数据库·mysql·代码规范
karry_k3 小时前
MyBatis批量insert-select踩坑:useGeneratedKeys=true 可能让PostgreSQL返回大量插入结果
java·后端
karry_k3 小时前
PostgreSQL 在 MyBatis 中执行正常 SQL 失效:一次 DELETE USING 踩坑记录
java·后端
Databend4 小时前
2KB histogram 背后:Databend 如何低成本追踪长尾延迟
大数据·数据分析·agent
这个DBA有点耶4 小时前
AI写的SQL跑崩了生产库,这锅谁背?
数据库·人工智能·程序员
镜舟科技5 小时前
Databricks 再提 LTAP,AI 时代的数据底座为何重回大一统叙事?
数据库·架构·agent
Databend6 小时前
从湖仓升级为 Agent 时代的数据控制面,Snowflake 和 Databricks 有哪些布局
大数据·数据库·agent
SamDeepThinking6 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
ClouGence9 小时前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
她的男孩9 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构