java常用命令

2020-06-28  本文已影响0人  7d972d5e05e8

一、查看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编译条件,你还看不到。。。大坑,网上很多资料都没说,导致用第一个版本的测试类,死活找不到想要看的方法。。。

上一篇下一篇

猜你喜欢

热点阅读