You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 15下Java agent抛出PreparedStatement NoClassDefFoundError

Java 15环境运行Java Agent抛出NoClassDefFoundError: java.sql.PreparedStatement问题分析
java.lang.NoClassDefFoundError: java/sql/PreparedStatement
    at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3325)
    at java.base/java.lang.Class.getDeclaredMethods(Class.java:2466)
    ...
Caused by: java.lang.ClassNotFoundException: java.sql.PreparedStatement
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:435)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    ... 19 more

核心成因

该异常的直接触发场景为:Java Agent通过反射扫描某类的声明方法时,JVM需要解析该类方法签名中引用的java.sql.PreparedStatement类型,此时当前类加载上下文无法加载对应类定义,就会抛出NoClassDefFoundError。结合Java 15的运行时规则,常见根因包括三类:

  • JPMS模块加载缺失:Java 9开始JDK核心类按模块拆分,java.sql.PreparedStatement隶属于java.sql模块,如果启动时通过--limit-modules参数限制了JVM加载的模块列表,未包含java.sql模块,就会导致该类完全无法被加载。
  • 类加载委托逻辑异常:按照JDK默认的双亲委派规则,java.*前缀的核心类应该由启动类加载器完成加载,URLClassLoader的findClass方法根本不应该参与这类核心类的查找。如果Java Agent自定义了独立的URLClassLoader实例,没有遵循双亲委派规则优先将JDK核心类的加载请求委托给上级类加载器,而是直接在自身的类路径下查找类,就会触发URLClassLoader查找JDK类的逻辑,最终抛出类不存在的错误。
  • 模块访问权限不足:即使java.sql模块正常加载,JPMS默认仅向未命名模块(类路径下的普通应用jar)开放模块的公共API访问权限,如果Agent做类反射解析时,所在的类加载上下文没有被授予java.sql模块的访问权限,就会触发类定义加载失败。

排查与解决方向

  • 排查JVM启动参数,移除/修正非法的--limit-modules配置,必要时添加--add-modules java.sql显式加载对应模块。
  • 检查Agent的自定义类加载器实现,补全双亲委派委托逻辑,对java.*前缀的核心类加载请求,直接委托给系统类加载器处理,不要在自定义类加载器路径下查找。
  • 针对JPMS访问限制,添加启动参数--add-opens java.sql/java.sql=ALL-UNNAMED,将java.sql模块下的类对所有未命名类加载上下文开放访问权限。
  • 如果使用字节码增强框架实现Agent的插桩逻辑,确认类签名解析、反射操作的类加载上下文与被增强的业务类保持一致,避免在隔离的类加载器上下文中触发JDK类的加载流程。

内容的提问来源于stack exchange,提问作者Piyush Moolchandani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.25 08:06:07