美文网首页
java常用命令

java常用命令

作者: 7d972d5e05e8 | 来源:发表于2020-06-28 19:32 被阅读0次

    一、查看class文件结构

    javap -v xxx,注意一定要在xxx.class文件所在目录下

    java重载是编译器来选择的,如下:

    Code:
          stack=2, locals=5, args_size=1
             0: new           #16                 // class com/example/demo/spi/Cat
             3: dup
             4: invokespecial #18                 // Method com/example/demo/spi/Cat."<init>":()V
             7: astore_1
             8: new           #19                 // class com/example/demo/spi/Dog
            11: dup
            12: invokespecial #21                 // Method com/example/demo/spi/Dog."<init>":()V
            15: astore_2
            16: new           #1                  // class com/example/demo/spi/ShadowTest
            19: dup
            20: invokespecial #22                 // Method "<init>":()V
            23: astore_3
            24: aload_3
            25: aload_1
            26: invokevirtual #23                 // Method sayHello:(Lcom/example/demo/spi/IShot;)V
            29: aload_3
            30: aload_2
            31: invokevirtual #23                 // Method sayHello:(Lcom/example/demo/spi/IShot;)V
            34: ldc           #27                 // String a
            36: astore        4
            38: aload_3
            39: aload         4
            41: invokevirtual #29                 // Method sayHello:(Ljava/lang/Object;)V
            44: aload_3
            45: bipush        98
            47: invokevirtual #32                 // Method sayHello:(C)V
            50: aload_3
            51: ldc           #35                 // String c
            53: invokevirtual #29                 // Method sayHello:(Ljava/lang/Object;)V
            56: return
    

    源码code:

      public static void main(String... args) {
            IShot c = new Cat();
            IShot d = new Dog();
            ShadowTest shadowTest = new ShadowTest();
            shadowTest.sayHello(c);
            shadowTest.sayHello(d);
    
            Object cha = "a";
            shadowTest.sayHello(cha);
            shadowTest.sayHello('b');
            shadowTest.sayHello("c");
        }
    

    可以看到,shadowTest.sayHello(c)的字节码指令,已经选择了:// Method sayHello:(Lcom/example/demo/spi/IShot;)V 这个重载的方法。🤣

    二、查看jvm运行参数

    1. jps -v 来实现,
    2. jinfo -flags <pid>。但是jinfo好像在java8有问题。但是我用java13也不行。。。
    3. ps -ef | grep java

    三、查看java代码的汇编指令:

    参考:
    查看Java的汇编指令
    下载macos的java汇编包
    上面环境准备好后,使用如下命令:

    java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly xxx (xxx是class文件)
    

    由于汇编内容太大,导致控制台输出被截断。需要使用重定向输出。如下:

    java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly VolatileTest.class > a
    

    a文件在当前执行命令的路径上,去该目录查看即可看到a文件。如下:


    image.png

    四、java hsdis 无法打印自己类的方法

    使用hsdis打印java源码的汇编,在生成的汇编文件中,总是找不到自己类方法的汇编。

    原因:没找到你想要看的方法,说明该方法没有进入JIT编译。没有进入JIT编译,说明该方法没有达到足够的调用次数。
    比如:

    public class VolatileTest {
        private static volatile int a = 0;
        public static void main(String[] args){
            test123();
        }
        private static void test123(){
            a += 1;
        }
    }
    

    上面的main方法在执行后,使用-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly是无法打印出test123方法的汇编的。因为没有达到足够的调用次数。改为如下即可:

    public class VolatileTest {
        private static volatile int a = 0;
        public static void main(String[] args){
            for(int i=0; i<50000; i++){
                test123();
            }
        }
        private static void test123(){
            a += 1;
        }
    }
    

    生成的汇编如下,由于文件很大,采用搜索指定方法查看:


    image.png

    当然这只是截取了片段。

    总结:-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly打印的是VolatileTest类执行时所有的JIT编译后的代码,肯定不止VolatileTest类里面的方法。相反VolatileTest类如果达不到JIT编译条件,你还看不到。。。大坑,网上很多资料都没说,导致用第一个版本的测试类,死活找不到想要看的方法。。。

    相关文章

      网友评论

          本文标题:java常用命令

          本文链接:https://www.haomeiwen.com/subject/mkoiwctx.html