跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Java Asm 修改 jdk 源码中的 ThreadPoolExecutor execute 不能引入 不是 jdk 的包下的类吗?
未分類
6 2 月 2021

Java Asm 修改 jdk 源码中的 ThreadPoolExecutor execute 不能引入 不是 jdk 的包下的类吗?

Java Asm 修改 jdk 源码中的 ThreadPoolExecutor execute 不能引入 不是 jdk 的包下的类吗?

資深大佬 : gengzi 6

提示 NoClassDefFoundError 。 还是说需要其他方式

大佬有話說 (9)

  • 資深大佬 : wsxyeah

    这些东西是用户机器上的,除非你打包一个 jre 进去

  • 主 資深大佬 : gengzi

    @wsxyeah 我在启用前使用 Agent,修改 jdk ThreadPoolExecutor execute 的方法,引入的 jar 应该会在运行时加载吧。

  • 資深大佬 : ffutop

    ThreadPoolExecutor 是被 Bootstrap ClassLoader 加载的。它的加载路径不包括你自定义的 MDCInheritableThreadLocal 。

    可以用 -Xbootclasspath 指定 Bootstrap 加载特定 Jar 包
    或者在 MANIFEST.MF 用 Boot-Class-Path 声明 Jar 包路径

  • 資深大佬 : kingfalse

    试试 javassist

  • 資深大佬 : fantastM

    在启动参数里用 -javaagent 的话,确实是如 #3 说的类加载问题。可以用 arthas 的 sc 、classloader 之类的命令来查看类的加载情况

  • 主 資深大佬 : gengzi

    @ffutop @fantastM ok,感谢解答。我去瞅瞅

  • 主 資深大佬 : gengzi

    @ffutop @fantastM 麻烦再咨询下,
    “`
    -javaagent:D:/ideaworkspace/baselog.jar -Xbootclasspath/a:D:/ideaworkspace/baselog.jar
    “`
    当这个键入 idea 中,运行 springboot 工程,提示 NoClassDefFoundError 关于项目中的引入的 jar,那这些 jar 我需要怎么引入。

  • 資深大佬 : fantastM

    简单回答:可以在 agent 中自定义类加载器,避免遵循 Java 类加载器中的双亲委派模型。

    详细回答:
    JVM 加载类是按照双亲委派模型来执行的,每个类都会优先委托给父类加载器来加载,当父类加载器无法加载类的时候再由子类加载器来加载,因此在 JVM 中加载的类会有一种层级关系。

    在你的例子中 `ThreadPoolExecutor` 会由 BootStrap ClassLoader 加载,参数 -javaagent 指定的 baselog.jar 包默认会由 System ClassLoader 加载,所以你一开始描述的问题原因是:`ThreadPoolExecutor` 类在被 BootStrap ClassLoader 加载之后链接的时候,无法找到需要被 System ClassLoader 加载的 baselog.jar 包里的 `MDCInheritableThreadLocal`。(注意这个问题是发生在链接阶段,这也是 JVM 为什么抛了 `NoClassDefFoundError` 而不是 `ClassNotFoundException` 的原因)

    然后你将 baselog.jar 包指定为由 BootStrap ClassLoader 加载,这样的话,`ThreadPoolExecutor` 类在被 BootStrap ClassLoader 加载、链接、初始化的时候,就可以找到同样是被 BootStrap ClassLoader 加载的 `MDCInheritableThreadLocal` 了。

    你在 #7 里说的事情,我理解为是你在 baselog.jar 包里用到了「项目中的引入的 jar 」(可能是 Spring 之类的吧),这部分包不由是 BootStrap ClassLoader 加载的,可能是 System ClassLoader,也可能是 Tomcat 的 Webapp ClassLoader,所以自然也会有 `ClassNotFoundException` 的问题。解决方案的话,我不建议把这类包也指定为由 BootStrap ClassLoader 来加载,更好的解决方案是自定义类加载机制,破坏一下 Java 类加载器中的双亲委派模型。

    具体实现的话,可以借鉴一些分布式追踪 APM 系统,它们在采集应用的数据时候,使用的无侵入式方案也是 javaagent,也会对项目中的一些代码做改造。

    一些可供查阅的资料:
    https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html
    https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html

  • 主 資深大佬 : gengzi

    @fantastM 听君一席话胜读十年书。昨天在查阅资料时,也考虑使用自定义的类加载器来尝试,我再去看看这块内容。非常感谢这么详细的解答。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具