Classic interview questions of large Java Internet companies, infinite thinking on the importance of JDK source code

On the importance of JDK source code: infinite thinking triggered by an interview question! What do you think when you see this title? Why are you talking about this?

So let's see what this interview question is. Almost like this interview question

The meaning of the title is: Two Integer type variables are defined, and the values ​​of these two variables are exchanged through the swap method.

Seemingly simple problem, do not know where to start, I guess some people think of this solution first: look at the code:

The results are as follows:

From the results it is wrong and does not solve our problem. Why?

 

Before analyzing, let's first introduce the way Java accesses objects. The Java heap must also contain address information that can find the object type data (such as object type, parent class, implemented interface, method, etc.), and these type data are stored in the method area.

Since the Java stack is a reference to the object, how do we use the object, there are two mainstream access methods: using handles and direct pointers .

(1) Using the handle:

If the handle access method is used, a piece of memory will be divided into the handle pool in the Java heap, and the handle address of the object is stored in the reference, and the handle contains the specific address information of the object instance data and type data, as shown in the figure: (2) Direct pointer

If the direct pointer access method is used, the layout of the Java heap object must consider how to place the relevant information of the access type data. The object address is directly stored in the reference, as shown in the figure: The access methods of these two objects have their own advantages, using the handle The biggest advantage of the access method is that the stable handle address is stored in the reference. When the object is moved (moving objects during garbage collection is a very common behavior), only the instance data pointer in the handle will be changed, and the reference itself does not need to be modified. .

The biggest advantage of using the direct pointer access method is that it is faster . It saves the time overhead of a pointer positioning. Since object access is very frequent in Java, this kind of overhead is also a very considerable execution cost. .

 

Then we return to the topic, here is also the first knowledge point to be talked about today: Java's pass-by-value In Java, there are two ways of passing by value: one is pass-by-value, and the other is pass-by-reference!

Then, passing by value means that when the current parameter is passed to the method, the variable in the method receives the copy value of the passed variable (equivalent to a copy of the value). Therefore, we modify the variable in the method. value, does not change the value of the outside variable.

Pass by reference: what is passed is a pointer to the address of the value

So, may I ask you, is it pass-by-value or pass-by-reference? Well, the old driver tells you that this is passed by value, why? Isn't Integer an object? Isn't object passing a pointer passed? Have you looked at the source code of the Integer class to see how this class is defined? Let's take a look. In fact, the final definition used by Integer means that the object instantiated by Integer cannot be changed. String is not about the same. So here is the value passed, let's draw the following picture:

So, let's first look at the Java runtime data area: 

We generally think that JVM only consists of heap and stack in development, but the actual Java virtual machine divides the memory it manages into several different data areas during the execution of Java programs. These areas have their own purposes and the time of creation and destruction. Some areas exist when the virtual machine process is started, and some areas are established and destroyed depending on the start and end of user threads. As shown below:

The memory in Java is mainly divided into two parts: the heap and the stack, the stack stores the variable itself, the heap stores the value of the object, and then executes the heap memory address through the stack to establish the relationship.

After passing the swap method: It means that two variables num1 and num2 will be created in the same way, and their values ​​are the values ​​of ab just copied. How does it change in memory at this time:

Everyone, you know why there is an address pointer, mainly because our heap memory mainly stores some objects, and the objects occupy the most memory. In order to save the space for internal slaves, this concept appeared. Well, at this point, at least everyone should be clear: the difference between passing by reference and passing by value.

Let's look at how this Integer is internally assigned. Let's take a look: Enter the Integer class Ctrl+o to search for the Integer constructor:

Then we find that this value is defined as a final type:

If he has a setValue() method, can we change the value through this method, but Integer does not provide it. That is to say, this method will not work. Well, then we will talk about the second knowledge point today: reflection Has anyone thought about using reflection when doing this topic?

Have you thought about it, see how many people have thought about this, did we just see that there is a value variable in the Integer class? Right, so we need to get this value variable and then change its value, right, then how do we do it, we can get this variable, this Filed through reflection, and then change its value, right? . Let's see how to write:

In theory, this method can definitely achieve our requirements. Run: Error: "Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final" "

It's wrong, isn't it, then this is another knowledge point:

Private member properties cannot be assigned through reflection!

So, what if you want to attack? In fact, in java reflection, a thing called setting access permissions is provided. Let's go into the Field class and see:

Then he has a setAccessible method in it:

This method is used to set the member attribute access rights. We see that the last is to give obj.override=flag

So let's go back and look at the set method of Field:

These few lines of code mean, that is, if override is false, Reflection.quickCheckMemberAccess(clazz, modifiers) is called to check access to member properties.

So, let's look at it again, at this time, can we set setAccessible(true) to true to mark the check that does not require access permissions. In this way, the value of value can be modified. Right. Let's try it out:

Well, everyone thinks this is no problem, the results are as follows:

The result is that the value of a has indeed changed, but the value of b has not changed. First of all, it is explained that the value can indeed be changed in this way, but why the value of b has not changed? . Why? Let's go back and look at the outer method again, and to check, we've defined:

Did you find any problems?

Is Integer an encapsulation type, and its value 1, 2 is an int type, a basic data type, so how is it assigned here? Then we write it normally like this:

int a = 1;

But why using Integer will not report an error, well, this brings us to another knowledge point: (notes)

Boxing and Unboxing in Java

 

Boxing : wrapping primitive types with their corresponding reference types to give them the properties of objects. int is packaged as Integer, float is packaged as Float;

Unboxing : Contrary to boxing, the object of reference type is simplified into data of value type;

Integer a = 100; // this is autoboxing (compiler calls static Integer valueOf(int i))
int b = new Integer(100); //this is auto-unboxing

So let's take a look at it actually, what we hear is false, what we see is true, let's take a look at the compiled bytecode file:

Command: javap -c Test.class

can be seen:

Jvm he automatically does the boxing operation, so you can see it clearly, right?

Well, let's take a look at Integer.valueOf(1): source code

It means that the value is greater than IntegerCace.low and less than IntegerCache.high:

It will be obtained from IntegerCache, that is, the value will be obtained from the cache.

So let's take a look at IntegerCache:

That is to say, all values ​​directly from -128 to 127 are obtained from the cache. When the value in the cache is put in, it is put in when the JVM starts, and then the memory address is allocated.

Have you noticed that you have so much knowledge in just a few lines of code? Do you feel like you don't know Java anymore? It's amazing, haha, okay, we have finished analyzing the first two lines of code, right, okay, then, we pass in the value of ab, and let's analyze this code in swap, okay, the essence is this code Ah, this is the essence, haha, let's see: breakpoint to this sentence

Then press F5 to go in and take a look, take out the value in IntegerCache and put it in notepat++

The first step: Do you need to get the value of num2, then he gets the value from the subscript [2+128=130]IntegerCache: 130 subscript, that is, the 131st number is: 2

The second step: field.set(num1,num2), means that the first step is to obtain the value of num1 in IntegerCache IntegerCache[1+128] = 1, and then modify the value of IntegerCache[num1] to num2 from Integercache The obtained value is 2, that is, modified to: integerCache[129] = 2

Step 3: The next line of code is executed

At this time, take out the IntegerCache again, then the value of the subscript 129, 130 becomes 2, and the value of tmp is 1, then the value obtained from the IntegerCache is IntegerCache[1+128=129], that is, 130 The number of rows, which is 2, so the result is this. It's actually the same as the following:

Go in from this sentence debug: find the cache that went away, and then find it from the 129th subscript in the cache.

So, when our value is in [-127-128], it is obtained from IntegerCache. In fact, we can verify this:

The result is: true

The result is: false

Well, at that time, I actually encountered this pit again, and I was pitted miserably, right? Hahaha.

So how do we solve the final question: (initial interview question)

1.

2.

3. The tricky way:

Alright. That's it!

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325340486&siteId=291194637
Recommended