History of Java Virtual Machine

  1. Sun Classic/Exact VM
  2. Sun Hotspot VM
  3. Mobile VM KVM/Squawk VM/JavaInJava
  4. BEA JRockit/IBM J9VM
  5. Others :Apache Harmony/Google Android Dalvik/Microsoft VM

Sun Classic VM: The world’s first commercial Java VIRTUAL machine that executes Java code in a purely interpretable manner and must be plugged-in to use the JIT compiler. The technology is primitive. The mission is over. JDK1.0

Sun Exact VM: a prototype of a modern high-performance virtual machine with a hybrid compiler and interpreter. Precise GC allows the virtual machine to know exactly what type of data is stored at a location in memory. JDK1.2

Sun Hotspot VM: The most widely used JVM today. Hot code detection technique: find the code that is most valuable to compile by executing a counter and then inform the JIT compiler to compile it on a method basis. JDK1.3 becomes the default VM

KVM,CDC/CLDC Hotspot Implenmentation, Squawk VM, JavaInJava, Maxine VM.

JRockit: Claims to be the world’s fastest Java VIRTUAL machine. In 2008 and 2009, Oracle acquired BEA and Sun respectively, integrated the two VMS and ported the excellent features of JRockit, such as JRockit’s garbage collector and MissonControl service suite, on the basis of HotSpot

Apache Harmony/Google Android Dalvik/Microsoft VM platform proprietary

Second, Java virtual machine running data area

Program counter: A line number indicator of the bytecode executed by the current thread, which is changed by the interpreter to select the next bytecode instruction to execute. Program counters are the only area in the Java Virtual Machine specification that does not specify any OutOfMemoryError exceptions.

Virtual machine stack: Describes the memory model of Java method execution. Each method execution creates a stack frame to store information about local variables, operand stacks, method exits, and so on. The stack of stacks. StackOverflowError is thrown if the thread request is deeper than the virtual machine allows. OutOfMemoryError is thrown if the virtual stack expands dynamically and sufficient memory cannot be allocated during the expansion.

Native method stack: The virtual machine stack serves Java methods and the Native method stack serves Native methods in much the same way.

Java heap: Shared by all threads, it is the largest chunk of memory managed by the Java virtual machine. The sole purpose of the Java heap is to hold object instances, and almost all object instances are allocated memory here. The Java heap, also known as the GC heap, is the main area managed by the garbage collector and can be subdivided into the new generation and the old generation. OutOfMemoryError is thrown when the heap cannot meet its memory allocation requirements.

Method area: Stores class information, constants, and static variables that have been loaded by VMS. It is also called permanent generation. The main targets for this area are constant pool reclamation and type offloading. Runtime constant pool: Holds various literal and symbolic references generated by the compiler. OutOfMemoryError is thrown when the method area cannot meet memory allocation requirements.

Garbage collection

Garbage collection is basically thinking about three things that a GC needs to accomplish:

1. Which resources should be recycled

Is the subject dead? How do I determine if an object is recyclable? There are two main methods: 1. Reference counting algorithm 2. Reachability analysis algorithm Reference counting method: add a reference counter in the object, every time there is a reference to it, the counter increases by 1; When a reference is invalid, the counter decays by 1; Objects with a counter of 0 are dead objects that can no longer be used. When two objects refer to each other, they are not reclaimed. The reference counting algorithm is not adopted by mainstream virtual machines mainly because it is difficult to solve the problem of circular references between objects.

Reachability analysis algorithm: through a series of objects called GC Roots as the starting point, search down from these nodes is called the Reference Chain. When an object is not connected to GC Roots by any Reference Chain (the object is unreachable), the object is unavailable.

2.When do you recycle?

To actually declare an object dead, there are at least two marking processes: if an object is found to have no chain of references linked to GC Roots after a reachabability analysis, it is marked for the first time and filtered once. The filter condition is whether it is necessary for this object to execute Finalize () method (for example, if the object does not rewrite Finalize () method or Finalize () method has been called by virtual machine, it is not necessary to execute Finalize () method). If necessary, the object is placed in an F-Queue and later executed by a low-priority Finalizer thread created by the virtual machine itself. The GC later marks the object in the f-queue a second time, and if the object is still not referenced, it is reclaimed.

3. How: How to recycle?

Main garbage collection algorithms: 1) Mark-sweep

Mark: First mark all objects that need to be reclaimed

Clear: All marked objects are uniformly reclaimed after marking is complete

Disadvantages Efficiency issues, both marking and cleaning processes are inefficient (too much space debris after collection, and recollection (during reachability analysis) sometimes requires traversing the entire memory region).

Space problem: a large number of discrete memory fragments will be generated after the mark is cleared. Too much space fragment may cause that later, when the program needs to allocate large objects, it cannot find enough contiguous memory and has to trigger another garbage collection action in advance.

2) Copying algorithms

Idea: Divide the available memory into two blocks by capacity and use only one of them at a time. When this block of memory is used up, the surviving objects are copied to the other side, and all that has been used is erased.

The advantage is that each time for the whole half of the memory reclamation, memory allocation does not have to consider the complex situation such as memory fragmentation, as long as the heap top pointer is moved, memory allocation in order, simple implementation, efficient operation.

Disadvantage is to reduce the memory for half of the original, rather too high a point.

98% of the objects in the new generation are “dead”, so instead of dividing the memory space in a 1:1 ratio, the memory is divided into a large Eden space and two smaller Survivor Spaces, using Eden and one Survivor at a time. In HotSpot, given the short lifetime of most objects, memory is divided into Eden and two Survivor, with a default ratio of 8:1:1. The cost is the existence of part of the memory space waste, suitable for use in the new generation.

3) Mark-Compact algorithm

The marking process is still the same as the mark-clean algorithm, but instead of cleaning up the recyclable objects directly, the next step is to move all surviving objects toward one end and then clean up memory directly beyond the end boundary.

4) Generational collection algorithm This algorithm is adopted by all current commercial VMS. According to the life cycle of objects, the memory is divided into several blocks. Generally, Java heap is divided into new generation and old generation, and appropriate collection algorithm is adopted according to each generation.

The new generation generally adopts Copying algorithms. The old generation’s first move uses mark-sweep or mark-compact for recycling.

4. Common Android memory leaks

1. Memory leaks caused by handlers

In Android development, we often use Handler to control the main thread UI changes. It is very easy to use, but if you don’t pay attention to it, you can easily cause memory leaks.

We know that Handler, Message, and MessageQueue are related to each other. The Handler interacts with the main thread by sending a Message. If the Message sent by Handler has not been processed yet, The Message and the Handler object that sent it will always be held by MessageQueue, which may make it impossible for the Handler to be reclaimed. The SecondActivity code has a Message that is delayed by 1 second. When the interface jumps from SecondActivity to ThirdActivity, the SecondActivity automatically goes into the background. If system resources are strained at this point (or if you open the “Do not keep Activity” option in Settings), SecondActivity will be finished. The problem is that SecondActivity’s Handler object, mHandler, is a non-static anonymous inner class object, and it automatically holds a reference to the external SecondActivity class, so SecondActivity cannot be reclaimed, causing a memory leak

Workaround: Declare the Handler as a static inner class, so that it does not hold a reference to the outer class SecondActivity, and its lifetime is independent of the outer class. If a context is needed inside the Handler, you can use weak references to the outer class.

Using the above method, we can avoid the SecondActivity memory leak by creating a static Handler inner class that holds an object context with a weak reference, but the Looper thread may have messages waiting to be processed in its message queue, so in the Activity onDestroy method, Also remember to remove pending messages from the message queue

2. Memory leaks caused by singleton pattern

Since the singleton life cycle is consistent with the life cycle of the app, it can easily cause memory leaks if used improperly.

This is the standard way to write a singleton pattern. On the surface, there’s nothing wrong with it, but if you’re careful, you’ll notice that when you’re building an instance of this singleton, you need to pass in a Context, and the Context that you pass in is very important. If you pass in an Activity, because the Context will always be held by the instance that you’re creating, When an Activity enters the background or opens an unreserved Activity in Settings, the Activity is destroyed, but the singleton holds its Context reference and the Activity cannot be destroyed, causing a memory leak

In the code above, SecondActivity2 contains an InnerClass InnerClass and creates a static instance of InnerClass mInner in the onCreate code that is consistent with the life cycle of the app.

This code is used in some scenarios, such as when an Activity needs to switch frequently or load a large number of images. Use this singleton after each Activity launch to avoid repeating stressful operations. This can cause a memory leak, however, because the non-static InnerClass InnerClass automatically holds a reference to the external class SecondActivity2, and the static instance mInner created will always hold the SecondActivity2 reference. Causes SecondActivity2 to not destroy properly when it needs to be destroyed.

The correct thing to do in this code is to make the InnerClass static to avoid memory leaks, because the static InnerClass no longer holds a reference to the outer class SecondActivity2.

Of course, you can isolate InnerClass as a single class and write it as a singleton to do the same thing without leaking memory.

Memory leaks caused by non-static inner classes creating static instances

In the code above, SecondActivity2 contains an InnerClass InnerClass and creates a static instance of InnerClass mInner in the onCreate code that is consistent with the life cycle of the app.

This code is used in some scenarios, such as when an Activity needs to switch frequently or load a large number of images. Use this singleton after each Activity launch to avoid repeating stressful operations. This can cause a memory leak, however, because the non-static InnerClass InnerClass automatically holds a reference to the external class SecondActivity2, and the static instance mInner created will always hold the SecondActivity2 reference. Causes SecondActivity2 to not destroy properly when it needs to be destroyed.

The correct thing to do in this code is to make the InnerClass static to avoid memory leaks, because the static InnerClass no longer holds a reference to the outer class SecondActivity2.

Of course, you can isolate InnerClass as a single class and write it as a singleton to do the same thing without leaking memory.

4. Listeners (various registered listeners, Watcher, etc.)

5, the resource object is not closed, causing a memory leak

6. Property animation

Listeners, resource objects, and animations should be shut down in time to avoid memory leaks

Author: Freely big front end R&D Center – Super ZO R&D group – Li Zhuxin

Recruitment information

Free big front end R&D center recruiting new students!

FE/iOS/Android engineer

Company benefits include:

  • Five insurances and one housing fund in full, plus commercial insurance
  • Free gym + annual physical examination
  • 10 percent discount for rent near the company
  • 2 promotions per year

Welcome to join us if you have passion for technology! Please send your resume to [email protected], or add wechat V-nice-V for details!