Java 中什么情况下类会被重载? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
biuaxia
V2EX    Java

Java 中什么情况下类会被重载?

  •  
  •   biuaxia 2023-04-10 19:34:45 +08:00 2461 次点击
    这是一个创建于 981 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目中有一个类 cn.qy.fk.util.PluginStarter, 当 org.hyperic.sigar.Sigar 的对象被 new 出来时, PluginStarter 整个类的方法都会被重载, 完整的代码我都贴在下面, 想问下大佬们我如果要修改方法内容, 应该如何操作呢?


    想要修改方法的类 cn.qy.fk.util.PluginStarter (从 jar 包中反译得来):

    package cn.qy.fk.util; @CustomFunction( type = 7 ) public class PluginStarter { public PluginStarter() { } public boolean start() { return (boolean)null; } public void end() { } } 

    项目运行时 cn.qy.fk.util.PluginStarter 实际的源码为:

    package cn.qy.fk.util; import cn.qy.fk.util.CustomFunction; import cn.qy.fk.util.SystemProperties; @CustomFunction(type=7) public class PluginStarter { public boolean start() { String error; if ((error = SystemProperties.get((String)"error")) != null) { System.out.println(error); return false; } System.out.println("Plugin Context is starting ..."); return true; } public void end() { System.out.println("Plugin Context was started!"); } } 

    注解 cn.qy.fk.util.CustomFunction (从 jar 包中反编译得来):

    package cn.qy.fk.util; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface CustomFunction { int type(); } 

    项目中用到了:

    • asm-9.1.jar
    • asm-attrs-1.4.1.jar
    • javassist-3.25.0-GA.jar
    • sigar.jar

    我通过 IDEA 的断点发现每当代码执行到了下面的 new Sigar(); 时类就被重载了.

    try { Sigar sigar = new Sigar(); (new PluginStarter()).start(); } 

    项目的资源目录还发现了:

    libsigar-amd64-freebsd-6.so libsigar-amd64-linux.so libsigar-amd64-solaris.so libsigar-ia64-hpux-11.sl libsigar-ia64-linux.so libsigar-pa-hpux-11.sl libsigar-ppc64-aix-5.so libsigar-ppc64-linux.so libsigar-ppc-aix-5.so libsigar-ppc-linux.so libsigar-s390x-linux.so libsigar-sparc64-solaris.so libsigar-sparc-solaris.so libsigar-universal64-macosx.dylib libsigar-universal-macosx.dylib libsigar-x86-freebsd-5.so libsigar-x86-freebsd-6.so libsigar-x86-linux.so libsigar-x86-solaris.so sigar-amd64-winnt.dll sigar-x86-winnt.dll sigar-x86-winnt.lib 

    想问下这种是不是被 jni 给重载了呢?如果要改的话怎么入手?

    11 条回复    2023-04-11 21:58:48 +08:00
    kyrieIvring
        1
    kyrieIvring  
       2023-04-10 21:31:58 +08:00
    一 看 classloader 是不是优先加载你这个 class ,如果是 强行改 classloader 的顺序
    二 看这个 class 是不是被编译进各个系统 jar 包里面了,如果是,你要找到对应的 jar 包,修改一下,再把它放回原来的位置
    biuaxia
        2
    biuaxia  
    OP
       2023-04-11 07:37:19 +08:00 via Android
    @kyrieIvring 确定不是 classloader 导致的,利用类加载机制覆盖也没法。
    biuaxia
        3
    biuaxia  
    OP
       2023-04-11 07:38:44 +08:00 via Android
    @kyrieIvring 贴出来的代码都是从三方 jar 包中反编译出来的,然后运行时通过阿里 arthas(可能拼错)运行 jad 得到的源码
    huyangq
        4
    huyangq  
       2023-04-11 09:07:58 +08:00
    不理解,什么叫类会被重载?我就知道函数(或者说方法、method)重载(overload)
    huyangq
        5
    huyangq  
       2023-04-11 09:13:57 +08:00
    仔细又阅读了一下,你的意思是有一个类 PluginStarter ,直接反编译 jar 包,发现改类中的 start()、end()的实现逻辑是 A ,但是当运行之后,如果执行到一行代码:new Sigar()之后,类 PluginStarter 中的 start()、end()的实现逻辑却成了 B 。
    huyangq
        6
    huyangq  
       2023-04-11 09:14:47 +08:00
    如果是这样,结合你的依赖包 asm 猜测是运行时修改了字节码实现的
    biuaxia
        7
    biuaxia  
    OP
       2023-04-11 09:50:31 +08:00
    @huyangq 是的,如果是运行时修改字节码,有什么方式可以实现我想要的修改吗?
    huyangq
        8
    huyangq  
       2023-04-11 09:55:53 +08:00
    你可以先确认是不是改的字节码,既然你说执行 new Sigar()会修改函数实现,你可在执行 new Sigar()之前、之后调用一下 start()、end()用来确定是否真的在 Sigar 构造函数中修改了函数实现,然后,再去看 Sigar 构造函数的实现 看看里头是不是真的又修改函数实现的代码,如果有,那简单啊 执行构造函数之后,再改成你要的函数实现就可以了
    vvtf
        9
    vvtf  
       2023-04-11 09:59:57 +08:00
    看下 java-agent 吧,
    是用 instrumentation 实现的.
    dif
        10
    dif  
       2023-04-11 10:56:49 +08:00
    有个成熟的监控项目 pinpoint 用到了类似的技术,你可以参考下。都是通过 java-agent 实现的。
    Aresxue
        11
    Aresxue  
       2023-04-11 21:58:48 +08:00
    类不会重载,只是会被 retransform ,简而言之就是方法体里面的字节码会被替换掉,JVMTI 提供了这样的机制,一般都是各种 agent 在启动时就会修改指定方法的字节码,不过也有些剑走偏锋直接在框架中用 asm 或者 javasist 修改的,像 HikariCP 就使用了各种字节码的黑魔法,可以看下有没有使用这两个框架的 api 的地方
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2843 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 14:32 PVG 22:32 LAX 06:32 JFK 09:32
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86