Before using bytecode files to analyze I = I ++, let’s look at some of the necessary pre-knowledge, which you can skip if you already know it

A simple concept

We used to say that Java is a cross-platform language, but why is Java cross-platform? The JVM is actually a specification, and HotSpot, J9, Taobao VM, Zing, and so on are its concrete implementations. At the same time, we can also think of the Java virtual machine as a piece of software running on the OS, in theory. Java files are compiled into class files, which are then parsed and executed by the JVM

With this in mind, since the JVM is the key to cross-platform, and the JVM is used to parse and execute class files, it follows that any language that can compile to class files can parse and execute on the JVM and be cross-platform

In fact, there are tons of languages that do this, not just Java! Scala, Kotlin, Groovy, Clojure, Jython (I wrote that correctly), and so on

From cross-platform languages to cross-language platforms

The structure of a bytecode file

Java applets don’t get much simpler than this one

package com.bl.classloader;



/**

* @Author BarryLee

*/

public class ByteCode1 {

}

We tried using Sublime to open the bytecode file it generated, following the first three lines in hexadecimal

cafe babe 0000 0034 0010 0a00 0300 0d07

000e 0700 0f01 0006 3c69 6e69 743e 0100

0328 2956 0100 0443 6f64 6501 000f 4c69

Oh, my God, it’s for people. Don’t worry. Let’s take a look at this

Then look one by one. If you are interested in JVMS, you can look at the official document

“CAFE BABE” is a class file named “CAFE BABE”. This is a class file named “CAFE BABE”. This is a class file named “CAFE BABE”

Minor Indicates the minor version number

Major version Specifies the major version number. In this case, 34 in hexadecimal corresponds to 52 in decimal, Java8

Constant pool_count Specifies the number of constants in the constant pool

Constant pool what’s in the constant pool, highlight, etc

Access Flags Class flags such as private, default, protected, public, class or Interface

This_class current class

Super_class, the superclass

Interface_count Number of interfaces

Interfaces Specifies the interface

How many fields does filds_count have

Fields is an attribute

Methods_count How many methods there are

What are methods and methods

Attribute_count Specifies the number of parameters

The attribute parameter, the most important thing is code — code

A great IDEA plugin

Hexadecimal numbers are really not for human reading, so install a plugin for your IDEA

View -> shwo bytecode with jclassLib -> Shwo Bytecode with jclassLib

Open ByteCode1

Isn’t it great? The plugin has already analyzed it for us

The general process of memory loading

  1. The Loading class loader loads a bytecode file from the hard disk to the VM memory

  2. Linking involves the following three steps

    Verification verifies that the bytecode file is valid and that Magic is cafe Babe

    Static variables are assigned default values (note that they are not the initial values you specify in your code)

    Resolution resolves symbolic references to direct references

  3. Initializing Static variable to an initial value

The JVM memory model is briefly reviewed

This is the last step. This is important.

Program Counter a Program Counter, PC for short, is the place where an instruction is placed, that is, it can be used to find the next instruction to be executed

If JVM Stacks are available, let’s leave it to the next section

If Native Method Stacks can be made, you can’t stack them

The Heap is where objects are stored, so that’s the focus of GC

Method Area. Method Area is just a concept. Implementation in 1.8 and later is called meta Space

Direct Memory Direct Memory

Talk about the JVM Stack

Each thread has a JVM Stack, and each JVM Stack has many Stack frames-stack frames. Each method has a Stack Frame inside the JVM Stack

So each Frame has four contents, which is what I = I ++ is all about, well, look at my Xmind, I’m not going to write it


I = I ++

If j = I ++, you know that j must be 8, but now I = I ++, the output is 8. Let’s analyze this little program at the bytecode level (open your jclasslib).

public static void main(String[] args) {    

int i = 8;

i = i++;

// i = ++i;

System.out.println(i);

}

Jclasslib: jclassLib: jclassLib: jclassLib: JclassLib: JclassLib

The following is the local variable scale mentioned earlier

Let’s do the instruction by instruction analysis

Bipush 8 pushes 8 (operand stack)

Istore_1, I put 8 on the stack first, and then put it on the local variable table, which is equivalent to assigning 8 to I

Iload_1, and then I’s 8 on the stack

Iinc 1 by 1 local change table No. 1 corresponding number +1 becomes 9

Istore_1 then pops the 8 on the stack to position 1 of the local table, overwriting it

So, I = I ++ ends up being 8, and the following instructions are to print and return

And let’s say I is equal to plus plus I

I don’t know if you can see the difference, but I = I ++ is pushing 8 first, and then popping up to cover the local variable table

So here I inc 1 by 1, and then I push 9, and I reassign to I, well, it’s an extra assignment, and I write ++ I

Again briefly read the following instructions 8^_^

Bipush -> b + I + push -> I small byte can hold the + variable I + stack

Istore -> I + store -> popstack then assigns the value of I to the local variable table

Iinc 1 by 1-> I + inc + 1 + by 1-> Local changes to the position of 1 + 1

I haven’t read getStatic either

Invokevirtual is a complex invoke instruction, and those of you who have studied reflection know that invoke is an execution method

  1. InvokeStatic executes static methods

  2. InvokeVirtual is a directive that comes with polymorphism, such as List l = new ArrayList(), which calls l.ad ()

  3. InvokeInterface interface,

  4. InovkeSpecial can be directly positioned, without the need for polymorphic methods private method, construction method

  5. Lambda expressions or reflection, which is the hardest instruction for the JVM, or other dynamic languages such as Scala kotlin, or CGLib ASM, dynamically generated classes

Well, no, I’m sure you’ve got the I = I ++ scoundrel meme all figured out by now