Follow Javac code to clarify matters bytecode

  Foreword  

  This article is a follow Nuggets booklet of them are "JVM bytecode from entry to the master" written exercises.

 

  problem

  Question one:

  We have the following code:

 1 package com.sun.tools.javac;
 2 
 3 /**
 4  * @author TY
 5  */
 6 public class Foo {
 7 
 8     public static void foo() {
 9         int a = 0;
10         int b = 6;
11         int c = 130;
12         int d = 33000;
13     }
14 
15 }

  Very simple piece of code, it seems there is no place worthy of discussion, but the code will see the next byte code with javap:

 

  Can be seen for different variable definitions, bytecode instructions are different, though are integers. . . Why do? Simple analysis can be learned, and it is

It has declared value relationship, different bytecode instructions for different size ranges. But our ideas on how to verify it? I believe many people are not aware of. We will be mentioned below how to verify

our thoughts.

 

 

  Question two:

  Note that the following code:

 1 package com.sun.tools.javac;
 2 
 3 /**
 4  * @author TY
 5  */
 6 public class Switch {
 7 
 8     public static void foo() {
 9         int a = 0;
10         switch (a) {
11             case 0:
12                 System.out.println("#0");
13                 break;
14             case 1:
15                 System.out.println("#1");
16                 break;
17             default:
18                 System.out.println("default");
19                 break;
20         }
21     }
22 
23 }

  Swtich ... case for some simple logic, there is no problem watching, take a look at the byte code:

 

  See above bytecode, using looupswitch, and we know that, switch ... case statement, there are two underlying command: tableswitch and looupswitch, before I

When studying just know tableswtich case value applies to a relatively compact case and is suitable for case lookupswitch value relatively sparse. But the above code

case values ​​are 0 and 1 ,,, this this this, sort of a kip sparse, so why should lookupswitch without tableswtich it?

  

  Source Javac

 

  We know that the Java code is compiled into byte code command is Javac, so on the above issues, we should look for answers in Javac source inside.

  First, download the source code Javac, here I offer them are the address provided: javac-Source-code-Reading

  After downloading a good open with IDEA:

  

 

 

  The above list is out of my own build, run javac entrance main function otherwise specified class will make an error code output directory.

  The need to set up the project which is set after the new directory:

  

 

 

   

  然后将com.sun.tools下面的两个包给排除掉,不然编译通不过

  

  这些做好之后就可以执行下javac的入口函数: com.sun.tools.javac.Main

  直接执行来看看:

  

 

 

   执行结果:

  

 

 

   好熟悉的输出,这不是在命令行里面直接执行javac的输出吗?

  

  所以,知道该怎么做了吧,需要加一个参数,参数就是要编译的java类的名字,我新建一个Hello类,随便写点啥。。。

  

  然后将Hello类的路径填写到Main的传入参数里面:

  

 

 

  再执行Main函数就可以看到Hello类的同级目录下就多了一个class文件:

  

 

 

   这就说明我们可以跟着Javac的源代码进行调试了,不过在此之前需要设置下:

  

  将Module source移到系统安装的JDK的前面,这样才能正常的调试而不是调试的时候跳转到安装的JDK里面去。

  可以调试Javac的代码意味着很多东西,我们遇到不理解的字节码的时候可以跟着Javac源码走一遍,看人家到底是怎么去实现的。

  接下来回到上面的两个问题,对应的Javac的源码分别在com.sun.tools.javac.jvm.Item类和com.sun.tools.javac.jvm.Gen类中,比如问题一代码对应下面:

  

 

 

  可以看到针对值得大小不同走了不同的逻辑:

  -1到5:iconst_0

  -128到127:bipush

  -32768到32767:sipush

  然后超过以上的范围则是:ldc

 

  而问题二对应的代码在Gen类visitSwitch方法中,重点代码是下面这段:

  

 

  hi和lo是在的代码逻辑中分别指向case的最大和最小值。我们将case值0和1代入其中:

  最终table_space_cost + 3 * table_time_cost = 15,而looup_space_cost + 3 * looup_time_cost = 13,

所以最终选用了lookupswitch指令。关于为什么要采用这样的算法我暂时不知,但至少对照着Javac源码知道了算法逻辑,不至于遇到

问题的时候一脸懵。。

  

  总结

  本文主要讲述了如何调试Javac源码以及如何运用Javac源码解答一些字节码的问题。

  另外,推荐掘金小册张师傅的小册《JVM字节码从入门到精通》

  可以扫描下面我分享的二维码购买,会便宜几块钱。。。(土豪不用管)

  

Guess you like

Origin www.cnblogs.com/alinainai/p/12123622.html