Interview: virtual machine stack 5 consecutive questions, I'm happy to hear it

Posted by shawjames on Sat, 12 Feb 2022 04:46:48 +0100

On the way to the interview

"Didi, Didi..." master, where are we? I'm in a hurry for an interview.

Master: it's almost there. It's the next intersection. I'm really convinced by these people. I can't drive all the way in.

Listening to the driver's complaints, I can't help thinking of a limerick poem: the tail lights are red all over the eyes and the flute is piercing in the ears. Worry about being late for a long time, decadent head like thunder.

As soon as I got off the bus, I trotted into the magnificent hotel. No, no, no, it's a business building. This hall is a little imposing, which makes me a little daydreaming.

Interview process

"Dong Dong", "please come in".

Interviewer: the young man is very handsome. Young people are just energetic. Let's introduce ourselves first.

Ah Q: Hello, interviewer. My name is "the master of shadow stream", from Ionia. It is the strongest single in LOL (no refutation is accepted). I haven't convinced anyone about single killing. My mantra is "invisible blade, the most deadly". Of course, you can also call me ah Q. this is my resume.

Interviewer: Ah Q, let's not exchange greetings. Let's get to the point. Since you have the most knowledge points written by jvm, let's talk about your understanding of virtual machine stack first.

Ah Q: inner OS: this wave can blow X. Cough... Cough... The virtual machine stack was also called java stack in the early days. It is a memory area existing in the runtime data area of the jvm. It is thread private. It is created as the thread is created and ends as the thread dies.

Um... Pretend to think about it 😄

As we all know, there are only two operations of stack in and out, so it is a fast and effective way to allocate storage. For it, there is no garbage collection problem, but its size is dynamic or fixed, so it will have stack overflow or memory overflow problems

Interviewer: Excuse me. You just said that there would be stack overflow and memory overflow. Can you explain why this happened?

Ah Q: Yes, we know that the virtual machine stack is composed of stack frames, and each method call corresponds to the stacking of a stack frame. We can set the stack size through the - Xss parameter. Assuming that the virtual machine stack size we set is very small, when we call too many methods, that is, too many stack frames, StackOverflowError will appear, that is, stack overflow problem.

If our stack frame is not fixed and set to dynamically expand, we will not have enough memory to support stack expansion when our memory is insufficient. At this time, there will be OOM exception, that is, memory overflow.

Interviewer: Uh huh (nodding), the young man has a clear idea. You just said that setting the stack frame too small will lead to stack frame overflow. Then we can completely avoid stack overflow by setting it larger.

Ah Q: I want to dig a hole for me. Like us, we generally advocate the golden mean. So when we hear this absolute problem, we must be smart: No, no, no, adjusting the size of the stack can only delay the time of stack overflow or reduce the risk of stack overflow.

For example 🌰 bar

  1. Suppose a business logic method needs to be called 5000 times, but a stack overflow error is thrown at this time. We can set - Xss to get more stack space, so that the call will overflow after 7000 times. At this point, adjusting the stack size becomes very meaningful, because this will enable the business to support normally.

  2. If there is dead recursion, no matter how to increase the stack size, it will overflow, which makes no sense.

Interviewer: OK, let's take a look at this simple small program. Can you roughly describe its execution process in memory?

 public void test() {
      byte i = 15;
      int j = 8;
      int k = i + j;
}

Let's have a picture for you to better understand

A Q: first compile the code, and then check its bytecode file. As shown on the left in the figure above, the execution process is as follows:

  1. First, the instruction address 0 to be executed is stored in the PC register. At this time, the data of the local variable table and the operand stack are empty;
  2. When the first instruction bipush is executed, put the operand 15 into the operand stack, and then set the value of the PC register as the execution address of the next instruction, that is, 2;
  3. When the operation instruction with instruction address 2 is executed, the data in the operand stack is taken out and stored in position 1 of the local variable table. Because this method is an instance method, the value of this is stored in position 0, and the value in the PC register becomes 3;
  4. Synchronization steps 2 and 3 put 8 into the operand stack first, and then take it out and store it in the local variable table. The value in the PC register also changes from 3 - > 5 - > 6;
  5. When the executed address instructions are 6, 7 and 8, reload the data with index positions 1 and 2 in the local variable table into the operand stack and perform iadd addition operation. The resulting value is stored in the operand stack, and the value in the PC register is also changed from 6 - > 7 - > 8 - > 9;
  6. Execute operation instruction istore_3. Take out the data in the operand stack and save it to the position with index 3 in the local variable table, execute the return instruction, and the method ends.

Interviewer: it seems OK. That's not bad. Can you say whether the local variables defined in the method are thread safe?

Q: let me give you a few more examples.

public class LocalParaSafeProblem {


    /**
     * Thread safe
     * Although StringBuilder itself is thread unsafe,
     * However, s1 variable only exists in the local variable table of this stack frame,
     * Because the stack frame is an independent part of each thread,
     * So s1 here is thread safe
     */
    public static void method01() {
        // It is created inside the thread and belongs to local variables
        StringBuilder s1 = new StringBuilder();
        s1.append("a");
        s1.append("b");
    }

    /**
     * Thread unsafe
     * Because StringBuilder is passed in as a parameter,
     * Other external threads can also access, so threads are not safe
     */
    public static void method02(StringBuilder stringBuilder) {
        stringBuilder.append("a");
        stringBuilder.append("b");
    }

    /**
     * Thread unsafe
     * At this time, StringBuilder is operated by multiple threads at the same time
     */
    public static void method03() {
        StringBuilder stringBuilder = new StringBuilder();
        new Thread(() -> {
            stringBuilder.append("a");
            stringBuilder.append("b");
        }, "t1").start();

        method02(stringBuilder);
    }

    /**
     * Thread unsafe
     * Because the method returns StringBuilder at this time
     * Other external threads can directly modify the reference of StringBuilder, so it is not safe
     */
    public static StringBuilder method04() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("a");
        stringBuilder.append("b");
        return stringBuilder;
    }


    /**
     * StringBuilder Is thread safe
     * At this time, the stringBuilder value exists in the local variable table of the current stack frame,
     * The reference cannot be accessed by other threads,
     * After the method is executed, the string builder in the local variable table is destroyed
     * Returned StringBuilder Tostring() thread unsafe
     * After the last return value returns toString, other threads can operate, and String itself is thread unsafe.
     */
    public static String method05() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("a");
        stringBuilder.append("b");
        return stringBuilder.toString();
    }
}

It is estimated that this will be a little windy. Let me summarize: if the object is generated inside the method and dies inside, there will be no thread safety problem if it will not return to the outside; On the contrary, if the class itself is thread unsafe, there will be thread safety problems.

Interviewer: it's good. It's reasonable. Tell me more about your understanding of heap memory.

Ah, I'm too tired today. I've been talking about this all day. I don't want to talk about it anymore.

Interviewer: Well, let's get here today and wait for the notice.

If you have any confusion, you can pay attention to gzh "Ah Q says the code" or add ah q's friend qingqing-4132. Ah Q looks forward to your arrival!

Topics: Java jvm Interview