V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
objcat
V2EX  ›  Java

Java 如何优雅地在 main 方法执行前后执行代码

  •  
  •   objcat · 2023-11-10 12:57:44 +08:00 · 2307 次点击
    这是一个创建于 404 天前的主题,其中的信息可能已经有所发展或是发生改变。

    白猫今天被难翻了, 研究了一上午也没有找到「如何在 main 方法执行前后执行代码」, 提这个问题的目的是, 我今天准备做个统计代码运行时间的工具, 这个非常简单, 就不多说了, 但是每次运行 main 方法的时候都要使用统计工具进行统计就很不雅观

    public static void main(String[] args) {
        ZYTime time = new ZYTime();
        System.out.println("hello world!");
        time.stop();
    }
    

    所以我想的是在main方法上加一个注解可以hook到方法执行前后的时刻, 比如

    public class Solution1 {
        @StatisticalTime
        public static void main(String[] args) {
            System.out.println("hello world!");
        }
    }
    

    我只想在这个解题的文件中优雅的统计执行时间, 请大神支招, 所谓优雅就是做完前置工作之后, 在真正需要用到功能的地方可以无痛使用, 除了注解还有没有其他解法呢, 白猫拜谢

    15 条回复    2023-11-13 11:26:47 +08:00
    pocketz
        1
    pocketz  
       2023-11-10 13:15:02 +08:00
    从 class loader 入手?
    Helsing
        2
    Helsing  
       2023-11-10 13:19:03 +08:00 via iPhone
    代码插桩啊,很成熟的方案了
    tool2d
        3
    tool2d  
       2023-11-10 13:20:40 +08:00
    说起来可能 OP 不信,我把所有的 java 都做了一个源代码级别的 processor ,直接一个#define 搞定一切。
    Ayanokouji
        4
    Ayanokouji  
       2023-11-10 13:21:26 +08:00
    搜 java agents
    chendy
        5
    chendy  
       2023-11-10 13:23:29 +08:00
    能用的方法很多很多,看你的需求和场景:
    1. 直接另起一个 java 进程,在外面统计时间
    2. 直接调用这个 main 方法,统计时间
    3. 批量处理代码文件,插上计时器再编译
    等等等等…
    janwarlen
        6
    janwarlen  
       2023-11-10 13:29:25 +08:00   ❤️ 1
    arloor
        7
    arloor  
       2023-11-10 13:41:28 +08:00 via Android
    agent premain
    aragakiyuii
        8
    aragakiyuii  
       2023-11-10 13:42:43 +08:00 via Android
    改 MANIFEST.MF
    cslive
        9
    cslive  
       2023-11-10 13:53:48 +08:00
    java agents
    v2e0xAdmin2
        10
    v2e0xAdmin2  
       2023-11-10 13:55:10 +08:00
    java agent premain
    yidinghe
        11
    yidinghe  
       2023-11-10 13:58:18 +08:00
    ···
    public class JavaLangTest {

    static {
    System.out.println("22222");
    }

    public static void main(String[] args) {
    System.out.println("11111");
    }
    }
    ···

    猜猜上面这段代码先输出 11111 还是 22222 ?
    yidinghe
        12
    yidinghe  
       2023-11-10 14:00:40 +08:00
    https://gist.github.com/yiding-he/78b02282ec27c4ae7b7dc31ee45fa64f

    猜猜上面这段代码先输出 11111 还是 22222 ?
    wang944294368
        13
    wang944294368  
       2023-11-10 14:57:44 +08:00   ❤️ 1
    jvm-sandbox
    ihuotui
        14
    ihuotui  
       2023-11-10 22:15:20 +08:00
    agent 技术,asm 或者 javassist
    Aresxue
        15
    Aresxue  
       2023-11-13 11:26:47 +08:00
    1.agent + 字节码改写 这个组合几乎可以做任何事情,但引入 agent 其实是个成本很高的事情还是要慎重;
    2.静态代理 对方法有入侵;
    3.定义一个函数把 main 传进去;
    4.字节码改写有三个时机,编译期织入、装载期织入、运行期织入,完全可以像 lombok 那样做一个编译期织入的注解,关键词 AbstractProcessor ;
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3113 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 13:39 · PVG 21:39 · LAX 05:39 · JFK 08:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.