当前位置:网站首页>Why recommend learning bytecode?

Why recommend learning bytecode?

2021-08-08 15:41:59 Mingmingruyue senior

Supporting video :

Why recommend you to study Java Bytecode

https://www.bilibili.com/video/av77600176/

 

One 、 background

This paper mainly discusses : Why study JVM Bytecode ?

Maybe a lot of people don't think it's necessary , Because it is not used for development at ordinary times , And not learning this doesn't delay learning .

But here's a little insight , That is, people always solve problems according to their own knowledge and skills .

Here's a paradox , Sometimes you think some technology is useless just because you don't master it , When you encounter a scene where you can use it, you can't think of using it .

 

1.1 From the point of view of life

If you are a non computer major , Your teacher took some pictures of your books , Probably 3000 word , Let you print into text .

You turn on the computer , A crackling knock , I've done it all afternoon .

If you know voice input , Then you may use voice input ,30 Minutes .

If you know OCR Picture text recognition , Probably 5 Minutes .

 

Different methods , The effect is completely different . But the most terrible thing is , You don't know voice input or OCR You don't feel like you're missing something .

OCR Recognition is definitely not something you can catch up with by improving your typing speed .

1.2 Study Java The angle of

Many people mainly rely on Baidu to learn knowledge , Dependent blog , Rely on video and books , And the quality of these materials is uneven , And it's the result of other people's understanding .

For example, you don't usually see the source code , Then you rarely use the source code as your learning material , Can only rely on blogs 、 The book 、 Video etc. .

If you usually like to watch the source code , You will have your own understanding of the source code , You will find that the source code is very helpful to your learning .

If you don't usually use decompilation and disassembly , Then you can only rely more on the source code , Rely on debugging and other learning knowledge , Instead of learning and understanding knowledge from the bytecode level .

When you slowly and skillfully read the virtual machine instructions , You will find that you have an additional way to learn knowledge .

 

Two 、 Why learn bytecode

2.1 People are always reluctant to leave the comfort zone

Many people are learning new knowledge , Always instinctively resist . Will find all kinds of reasons not to learn ,“ For example, I can't use it for the time being ”,“ It's no use learning ”,“ later ”.

Even think it's a waste of time .

 

2.2 Why learn bytecode ?

I've been studying for some time recently JVM Knowledge of bytecode , Although not proficient , But it's not too hard to read bytecode .

The reason why learning bytecode is recommended is that it can be learned from a deeper level than the source code Java Related knowledge .

Although it is impossible to solve all problems with bytecode knowledge , But it gives you a way to learn .

For example, by learning bytecode, you can better understand  Java The principles behind various grammars and grammatical sugars in , Better understanding of language features such as polymorphism .

 

3、 ... and 、 give an example

This paper gives a simple example , To illustrate the role of learning bytecode .

3.1  Example

3.1.1 Grammatical sugar

public class ForEachDemo {

    public static void main(String[] args) {

        List<String> data = new ArrayList<>();
        data.add("a");
        data.add("b");
        for (String str : data) {
            System.out.println(str);
        }
    }
}
  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

compile : javac ForEachDemo.java

Disassembly :javap -c ForEachDemo

public class com.imooc.basic.learn_source_code.local.ForEachDemo {
  public com.imooc.basic.learn_source_code.local.ForEachDemo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/util/ArrayList
       3: dup
       4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #4                  // String a
      11: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      16: pop
      17: aload_1
      18: ldc           #6                  // String b
      20: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      25: pop
      26: aload_1
      27: invokeinterface #7,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      32: astore_2
      33: aload_2
      34: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
      39: ifeq          62
      42: aload_2
      43: invokeinterface #9,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      48: checkcast     #10                 // class java/lang/String
      51: astore_3
      52: getstatic     #11                 // Field java/lang/System.out:Ljava/io/PrintStream;
      55: aload_3
      56: invokevirtual #12                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      59: goto          33
      62: return
}

  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

We can see it clearly foreach The iterator implementation is used at the bottom of the loop , You can even reverse the brain to make up the corresponding Java Source code ( You can try to write equivalent source code according to bytecode ).

 

 

3.1.2 A problem encountered in reading the source code

When we read the source code, we often encounter the following writing method :

org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#startWebServer

	private WebServer startWebServer() {
		WebServer webServer = this.webServer;
		if (webServer != null) {
			webServer.start();
		}
		return webServer;
	}
  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

Declare a local variable with the same name as the member variable in the function , Then assign member variables to local variables , Use it again .

Seemingly small details , There is an idea of optimization .

Maybe some people have read some articles and mentioned ( But why do we always have to see an article and a knowledge ? What if I don't see it ?), More people may not understand what optimization is .

 

3.2 simulation

Ordinary grammar sugar doesn't expand too much here , Focus on the second optimization example .

Imitate the example of the above writing :

public class LocalDemo {

    private List<String> data = new ArrayList<>();

    public void someMethod(String param) {
        List<String> data = this.data;
        if (data != null && data.size() > 0 && data.contains(param)) {
            System.out.println(data.indexOf(param));
        }

    }

}
  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

compile :javac LocalDemo.java

Disassembly : javap -c LocalDemo

public class com.imooc.basic.learn_source_code.local.LocalDemo {
  public com.imooc.basic.learn_source_code.local.LocalDemo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: new           #2                  // class java/util/ArrayList
       8: dup
       9: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
      12: putfield      #4                  // Field data:Ljava/util/List;
      15: return

  public void someMethod(java.lang.String);
    Code:
       0: aload_0
       1: getfield      #4                  // Field data:Ljava/util/List;
       4: astore_2
       5: aload_2
       6: ifnull        41
       9: aload_2
      10: invokeinterface #5,  1            // InterfaceMethod java/util/List.size:()I
      15: ifle          41
      18: aload_2
      19: aload_1
      20: invokeinterface #6,  2            // InterfaceMethod java/util/List.contains:(Ljava/lang/Object;)Z
      25: ifeq          41
      28: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: aload_2
      32: aload_1
      33: invokeinterface #8,  2            // InterfaceMethod java/util/List.indexOf:(Ljava/lang/Object;)I
      38: invokevirtual #9                  // Method java/io/PrintStream.println:(I)V
      41: return
}

  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.

here In the local variable table 0 by this , 1 by param  2 by local variable   data

Examples of using member variables directly :

public class ThisDemo {


    private List<String> data = new ArrayList<>();

    public void someMethod(String param) {

        if (data != null && data.size() > 0 && data.contains(param)) {
            System.out.println(data.indexOf(param));
        }

    }
}
  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

compile :javac ThisDemo.java

Disassembly : javap -c ThisDemo

public class com.imooc.basic.learn_source_code.local.ThisDemo {
  public com.imooc.basic.learn_source_code.local.ThisDemo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: new           #2                  // class java/util/ArrayList
       8: dup
       9: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
      12: putfield      #4                  // Field data:Ljava/util/List;
      15: return

  public void someMethod(java.lang.String);
    Code:
       0: aload_0
       1: getfield      #4                  // Field data:Ljava/util/List;
       4: ifnull        48
       7: aload_0
       8: getfield      #4                  // Field data:Ljava/util/List;
      11: invokeinterface #5,  1            // InterfaceMethod java/util/List.size:()I
      16: ifle          48
      19: aload_0
      20: getfield      #4                  // Field data:Ljava/util/List;
      23: aload_1
      24: invokeinterface #6,  2            // InterfaceMethod java/util/List.contains:(Ljava/lang/Object;)Z
      29: ifeq          48
      32: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
      35: aload_0
      36: getfield      #4                  // Field data:Ljava/util/List;
      39: aload_1
      40: invokeinterface #8,  2            // InterfaceMethod java/util/List.indexOf:(Ljava/lang/Object;)I
      45: invokevirtual #9                  // Method java/io/PrintStream.println:(I)V
      48: return
}

  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

At this time, there are only two local variable tables , namely   this and   param.

You can also go through   javap -c -v To see more details , In the screenshot of this example IDEA Plug in jclasslib bytecode viewer, If you are interested, please refer to my other blog post about the tool :《IDEA Bytecode learn to view artifact jclasslib bytecode viewer Introduce 》.

 

3.3 analysis

Through the source code, in fact, we can't well understand where the optimization is .

After we compile and disassemble the two classes respectively, we can clearly see : The first example code is one more line , Instead, the decompiled bytecode is shorter .

Where is the length of the decompiled bytecode in the second example longer than that in the first example ?

We found that most of them are in :getfield      #4                  // Field data:Ljava/util/List;  here .

That is, every time you get data Objects must first   aload_0 And then again  getfield Instructions for .

The first example is through astore_2 Save it in the local variable table , Use it directly every time aload_2 Loads the operand stack directly from the local variable table .

So you don't have to start from this Object , So it's more efficient .

 

This idea is a bit like the cache commonly used in writing code , Check the data to be used recently and cache it , When using, first check the cache .

It essentially embodies the concepts of temporal locality and spatial locality in the operating system ( If you don't understand, turn to the book or Baidu ).

Therefore, through the analysis of bytecode , Through practical development experience , By connecting expertise , We have figured this out .

 

In addition, it also embodies the idea of exchanging space for time .


Only knowledge can run through , The ability to understand is stronger .

The importance of professional foundation is also reflected here .

In addition, knowledge can be linked 、 Think about the essence , Understanding is more profound , Memory can be stronger , It is more possible to use .

Four 、 summary

This is just a very typical example , Study JVM Bytecode can give you a different perspective , Let you have another way to learn .

Maybe many people say they want to learn, but they can't start , I recommend you to look at 《 In depth understanding of Java virtual machine 》, Then combine 《Java Virtual machine specification 》, Usually knock more javap Instructions , I'm getting familiar with it , In addition, I strongly recommend jclasslib bytecode viewer plug-in unit , The plug-in can click the command to jump to Java The introduction of this instruction in the virtual machine specification , It is of great help to learning .

A lot of people would say , Learning this is too slow .

You bet , Eager for success, how can you learn very well ? A thick product makes a thin hair , Can't stand loneliness, how can you achieve something .

Through one of these examples, this paper makes you understand ,JVM Bytecode can help you understand Java Some of the syntax ( Limited space , And there are too many examples , I won't give you , Interested students try it by themselves ), Even help you learn the source code .

Just imagine , If you think learning bytecode is useless , You don't even know , How can you use it to solve problems ?

The knowledge you have helps you grow and limits your growth , Dare to break through the comfort zone , Give yourself more growth opportunities .

 

 

版权声明
本文为[Mingmingruyue senior]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/08/20210808153459076c.html

随机推荐