Interviewer: What is the result of the following code execution? String t0 = “helloworld”; String t1 = new String(“helloworld”); System.out.println(t0==t1); Xiao Bai: it can’t be so simple

Interviewer: Explain in detail why? Create a String variable t0 in the Java virtual stack, and first look for the same String in the runtime constant pool of the method area. If the same String already exists, the t0 variable in the stack points directly to that String. If not, create a “HelloWorld” string in the constant pool and point the t0 variable on the stack to that string. Create a string object using the new keyword. First, when the current class is loaded, the runtime constant pool will look for the existing “HelloWorld” string. If not, the compile-time generated “HelloWorld” will be stored in the runtime constant pool. Generates an object of type String in the heap, to which the stack t1 variable points. Because t0 and T1 refer to different objects, when using ==, we compare references to objects (which could be a reference pointer to the object’s starting address, a handle representing the object, or some other location associated with the object), and naturally return false.

Interviewer: What is the result of running the following code? String t0 = new String(“hello”) + new String(“world”); t0.intern(); String t1 = “helloworld”; System.out.println(t0 == t1); JDK1.7: false for versions prior to JDK1.7, true from JDK1.7.

Interviewer: Why are the results different? In versions prior to JDK1.7, the intern method first looks for the same string in the runtime constant pool of the method area. If it already exists, it returns the existing string. Otherwise, it adds a string constant to the constant pool and returns the string. Since JDK1.7, the HotSpot virtual machine has moved string constants to the Java Heap. The implementation of intern has also been changed. First, it queries the constant pool to see if it already exists. Instead, you just keep references to string objects in the constant pool.

Interviewer: What about the Java virtual machine stack in the JVM runtime data area? White: The Java virtual stack is thread private. Each thread has its own Java virtual stack. Its life cycle follows the thread, which is created when it starts and destroyed when it ends. When a Java method is executed, a corresponding stack frame will be created. The stack frame stores method local variation table, operand stack, dynamic link, method exit information, etc. This process is called pushing. When the method completes execution, the corresponding stack frame is destroyed, a process called unstack.

Interviewer: How do you understand local variable tables, operand stacks, dynamic links, and method exit information? Small white: The local variable table mainly stores method parameters and local variables defined inside the method. If it is a basic data type, the value of its variable is stored; if it is a reference type, the object reference is stored. The operand stack can be understood as the data and result data that need to be processed during an operation; Each stack frame contains a reference to the method that the stack frame belongs to in the runtime constant pool. Converting symbolic references to direct references during method calls is called dynamic linking. The method exit information records the location of the upper level caller that should be returned to after the current method completes normal execution, or the location of the exception handling that should be returned to when the method exits.

Interviewer: Object references are stored in the local variable scale. How do I find objects through this reference? Xiaobai: Normally, objects are created and stored in the heap. Objects in the heap can be accessed through handles and direct Pointers. Handle way: in the Java heap divides the handle to an area called pool, object reference stored in local variables is the address of a handle, through this address to handle pool found handle, handle address and store the object instance data object type the address of the data, through the actual data of the object and the object they can find the type of information. Direct Pointers: local variables in the object is the object of the storage address, through this address can be found directly in the heap object, at the same time also stored in the object instance data object type address, through this address can be found in the methods section corresponding to the object type information, HotSpot virtual machine to use this way.

Interviewer: Speaking of references, what kinds of references are there in Java? What are they? Xiao Bai: According to the strength of a reference, There are four types in Java: strong reference, soft reference, weak reference, and virtual reference. Strong references, such as Object obj = new Object(); Obj’s reference to an Object instance is a strong reference. Soft references, such as Object obj = new Object(); SoftReference sf = new SoftReference(obj); Here sf is a soft reference to OBj, and the object referenced by the soft reference is garbage collected before the system is about to run out of memory. Weak references, such as Object obj = new Object(); WeakReference wf = new WeakReference(obj); Where WF is a weak reference to OBj, the object referenced by the weak reference will be collected when garbage collection occurs. Virtual references, such as Object obj = new Object(); PhantomReference pf = new PhantomReference(obj); In this case, PF is a virtual reference to OBj, and the object associated with the virtual reference will receive notification from the system when it is collected, which is mostly used to track the garbage collection process.

Interviewer: The source code implementation of ThreadLocal uses weak references. Are you familiar with this? Xiao Bai: The implementation principle of ThreadLocal is that each Thread maintains a ThreadLocalMap mapping table. The key of the mapping table is the instance of ThreadLocal, and the weak reference of ThreadLocal is used. The value of the mapping table is the Object to be stored. A graph shows the reference relationships between these objects, with solid arrows representing strong references and hollow arrows representing weak references.

Interviewer: So how does the memory leak from weak references in ThreadLocal happen? Small white: If a ThreadLocal has no external strong references, the ThreadLocal must be collected when garbage collection occurs (weak references are collected regardless of whether the current memory is sufficient or not), resulting in null entries in the ThreadLocalMap. The external will not be able to obtain the value of these entries with a null key, and if the current thread is always alive, there will be a strong reference chain: Thread Ref -> Thread -> ThreaLocalMap -> Entry -> Value. As a result, the Object corresponding to the value cannot be reclaimed, resulting in memory leakage.

Interviewer: How do you solve it? Small white: The get, set, and remove methods of ThreadLocal remove all values with a null key. However, a memory leak can occur when a ThreadLocal get or set method is used. A null value will not be cleared if the get, set, or remove methods are not called thereafter. The solution is to call its remove() method every time a ThreadLocal is used to remove data, or as the JDK recommends, make the ThreadLocal variable private static so that a strong reference to ThreadLocal always exists. This ensures that the Entry value can be accessed through ThreadLocal’s weak reference at any time, and then erased.

One small question, the output is true? false? String t0 = “a”; String t1 = “b”; String t2 = t0 + t1; String t3 = “ab”; System.out.println(t2==t3);

Focus on not getting lost, documenting backend development