1 Object memory structure and pointer compression understand


// class oopDesc in hotspot oop. HPPclass oopDesc {
  friend class VMStructs;
  private:
volatile markOop _mark; // Object headerUnion _metadata {// klassOop class metadata pointer Klass* _klass;  narrowKlass _compressed_klass;  } _metadata; Copy the code
  • Object instance data memory consists of three parts: the Object header, the actual data area, and the memory alignment area
  • The object header layout is as follows: locks, hashcode, garbage collection; The locking mechanism is too long to explain here; The lock-related markOop memory layout is as follows
  • What is memory alignment? HotSpot VM’s automatic memory management system requires that the object’s starting address be an integer multiple of 8 bytes, in other words, the object’s size must be an integer multiple of 8 bytes. Therefore, when the object instance data part is not aligned, it needs to be completed by alignment padding.
  • Memory alignmentbenefits
    • Facilitate memory management
    • Faster CPU reads. The CPU gets data from memory, not in bytes, but as long as the CPU can process it. For example, in a 32-bit machine, it is a 4-byte block of memory. When only two of these bytes are needed, the memory processor handles the selection. If you need three bytes spread across two different memory blocks (a four-byte memory block), you need to read the memory twice (only once if the same memory block exists). When objects are properly aligned according to certain rules, the CPU can make minimum requests for memory and speed up CPU execution
  • Pointer to the compressed
    • As you can see in the figure above, the Object MarkWord is twice as large in a 64-bit JVM as it is in a 32-bit JVM. KlassOop also doubles to 64 bits (the array length is fixed at four bytes). The pointer width increases, but for less than 4 gb of heap memory, it doesn’t seem to be necessary to use a 64-bit pointer. Can this be optimized? The answer is pointer compression
    • The principle of pointer compression is to use THE JVM to implant compression instructions for encoding and decoding
    • What information will be compressed
      • Objects to be compressed: class attributes, object header information, object reference types, object array types
      • Uncompressed objects: Pointers to local variables, stack elements, incoming parameters, return values, NULL
    • With pointer compression enabled, klassOop size can be changed from 64bit to 32bit. JVM – Anatomy of pointer compression for JAVA OBJECT headers
    public static void main(String[] args){
    Object a = new Object(); // 16B close compression is still 16B, need to be 8B multiples; 12B plus 4B filledint[] arr = new int[10]; // 16B off compression is 24B}
    
    public class ObjectNum {  //8B mark word //4B Klass Pointer uses 8B if compression is turned off/ / - XX: - UseCompressedClassPointers or - XX: - UseCompressedOops, int id; //4B String name; //4B takes up 8B if compression is turned offbyte b; //1B actual memory may be filled up to 4BObject o; //4B takes up 8B if compression is turned off} Copy the code
    • Why, when pointer compression is turned on, the heap should not exceed 32GB and Pointers use 32 bits. Why is the maximum available memory 32GB instead of 4G

      The JVM requires that the object’s starting position be aligned to multiples of 8 bytes, which can be used to elevate the location range, theoretically up to2^11 * 4G. But the JVM only moves the pointer three places to the left, so2^3 * 4G = 32G. ifMore than 32 gbPointer compression will fail. If the GC heap size is inThe following 4 g, directly cut the high 32 bits, avoiding the encoding and decoding process
    • Enable pointer compression-XX:+UseCompressedOops(The default open) to disable pointer compression:-XX:-UseCompressedOops

2 Some basic methods of Object

  • Local method
    • private static native void registerNatives()Link native methods defined by Object to Java programs.RegisterNatives in the Object class
    • public final native Class<? > getClass()Get the Java Class metadata
    • public native int hashCode()Gets the hash Code of the object
    • protected native Object clone() throws CloneNotSupportedExceptionGet the clone object of the object, shallow copy
    • public final native void notify()Wakes up the wait object to lock a thread in the waitSet queue
    • public final native void notifyAll()Like notify(), the wait object wakes up all threads in the waitSet queue
    • public final native void wait(long timeout)Release the object lock and enter the waitSet queue for the object lock
  • Common methods
    public String toString() { return getClass().getName() + "@"+ Integer.toHexString(hashCode()); }public boolean equals(Object obj) { return(this == obj); }public final void wait(long timeout, int nanos) throws InterruptedException;
    // Both are based on native voidwait(Long timeout) implementedpublic final void wait() throws InterruptedException;
    wait(long timeout, int nanos),wait(a)// This method is specifically called by the JVM before the object is reclaimedprotected void finalize() throws Throwable; Copy the code

3 ==, equals, Comparable.compareTo, Comparator.compara

If the sort order is not specified, the default sort order in Java is ascending, from smallest to largest

  • ==, (A) for comparison between primitive types are values, (B) for comparison between primitive types and encapsulated types are value comparisons, and (C) for comparison between reference types are memory addresses
  • Equals (Object o) can be seen in the Object base methodpublic boolean equals(Object obj) { return (this == obj); }We use == to compare. The nice thing about equals is that we can override it
  • Comparable.compareTo is an abstract method in the Comparable interface; If the object implements this interface, collections.sort (List< T> col) can be used for sorting. Next look at the source code how to achieve
    Collections.java
    // collections.sort (List<T> List), which calls the List sort methodpublic static <T extends Comparable<? super T>> void sort(List<T> list) {
        list.sort(null);
    }
    Copy the code

    The sort of List calls arrays.sort

    List.java
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
     for (Object e : a) {  i.next();  i.set((E) e);  } } Copy the code

    Arrays.sort(Object[] a) is called if the Comparator c is null; The final call to LegacyMergeSort(merge sort) method processing

    Arrays.java
    public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
     if (LegacyMergeSort.userRequested)  legacyMergeSort(a, c);  else  TimSort.sort(a, 0, a.length, c, null, 0, 0);  } } Copy the code

    A piece of code in the LegacyMergeSort method; Finally, the bottom layer is usageMerge sortAnd compareTo

    Arrays.java
    .    if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
     ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)  swap(dest, j, j-1);  return;  } Copy the code
  • Comparator is also an interface, but it provides richer operations that need to be implementedint compare(T o1, T o2)methods

    The Comparator provides the static methods thenComparing, Reversed, and reverseOrder (a Comparator or Comparable is required to operate on objects). It can be used with list. sort, stream. sorted, and collections.sort.
    @Data
    @AllArgsConstructor
    static class Pair implements Comparator<Pair>, Comparable<Pair> {
        Integer one;
        Integer two;
     @Override  public String toString() { return one + "-" + two; }  @Override  public int compareTo(Pair o) { return one.compareTo(o.one); }  @Override  public int compare(Pair o1, Pair o2) {returno1.compareTo(o2); }} public static void main(String[] args) {  List<Pair> col = Arrays.asList( new Pair(4, 6), new Pair(4, 2),new Pair(1, 3));  col.sort(Comparator.reverseOrder());  System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");  col.stream().sorted(Comparator.comparing(Pair::getOne).thenComparing(Pair::getTwo))  .forEach(item -> System.out.println(item.toString()) ); } Copy the code

    Collections.sort is sort ascending by default, and you can see that reverseOrder reverses the order; Col using thenComparing first judges the size of Pair::getOne, and then sorts Pair::getTwo if they are equal

    result:
    4 to 64-2
    1-3
    ----------------
    1-3 4-2 4 to 6Copy the code

4 method overrides and overloads

  • Method rewriting refers to methods whose subclass definition and parent class method name, parameters, and order are the same. Note that subclass overriding method modifiers cannot be stricter, that is, the superclass method modifiers are protected, subclasses cannot use private modifiers instead of public, and cannot throw exceptions that are more broadly defined than the superclass method
  • An overload of a method is a method defined in the same class with the same name as an existing method but with different arguments or arguments in different order. (The return value does not determine the overload of the method.)
  • Overridden methods can be determined at compile time (compile-time polymorphism), while overridden methods need to be determined at run time (run-time polymorphism). The three necessary conditions for polymorphism are 1, there are inheritance relationships 2, the subclass overrides the parent class method 3, and the parent class references refer to the subclass object

5 Whether the constructor can be overridden

Constructors are unique to each class and cannot be inherited by subclasses because a constructor does not return a value and a subclass cannot define the same method as its parent class’s constructor. But within the same class, constructors can be overloaded

public class TestEquals {
    int i;
    public TestEquals() {   i = 0; }
// Constructor overload    public TestEquals(int i) {   this.i = i } 
} Copy the code

6 Object equals and hashCode

Equals is used to compare whether two objects are equal. You can override this method to implement a custom comparison method. HashCode is used to get the hash value of an object, and you can override this method. When objects are stored in a Map, object. hashCode is first used to determine whether they are mapped in the same location. If they are mapped in the same bit, equals is then used to compare whether the two objects are identical.

7 What’s wrong with equals and hashCode?

Overwriting equals results in the same object comparison but different hashCode is a violation of the JDK specification; Also, when using HashMap storage, there may be multiple objects that we define as the same, which can create holes in our code logic.

8 Object. Wait and Thread. The sheep

Object. Wait is used within synchronized modified code, which cedes the CPU and relinquishes the holding state for the Object lock. Thread.sleep simply suspends, freeing the CPU without freeing any lock resources

9 Use of finalize method

  • If an object overrides the Finalize method, the JVM registers the current object in the FinalizerThread ReferenceQueue queue. When garbage is collected, the JVM determines that the ReferenceQueue exists and does not collect the object. The FinalizerThread (separate from the garbage collection thread) then retrieves the object from the ReferenceQueue, executes a custom Finalize method, and removes the object from the queue for the next garbage collection
  • Finalize will cause object collection delay, which may lead to memory overflow, so use with caution
  • Finally is different from Finalize
    • Finally is a Java keyword used to handle exceptions. It is used with try
    • Will the finally block execute if it returns before finally? A continue,break, or return ina try cannot circumvent execution of a finally block. Finally must be executed after the try ends
  • Similar keyword final
    • Final decorates a class that cannot be inherited; Modifier methods that cannot be overridden; Modify variables that cannot point to new values; Modifier arrays. Array references cannot point to new arrays, but array elements can be changed
    • If the object is final, how many ways can a variable be declaratively assigned?
    • Fianl modifies ordinary variables: 1. Declaration at definition 2. Declaration of in-class code blocks 3
    • Fianl modifies static variables: 1, declaration at definition, 2, static code block declaration within a class

What are the methods for creating objects

  • 1. Create with new
  • 2, Use reflection to create a Class at newInstance()
  • Call the clone() method of the object
  • 4. Obtained by deserialization, e.g.ObjectInputStream.readObject()

11 Guess the number of objects created

  • String one = new String("Hello");

    Two objectsAnd aStack variable: a stack variable one and an instance object of new String(), and a “hello” String object

  • Digression: string. Intern (); Intern checks whether the constant pool contains the same string and returns the reference if it does. Otherwise, the first occurrence of a reference to the string in the heap is recorded in the constant pool and the reference is returned.

    If it is executed firstString s = "hello" ;Execute intern(); “Hello” is created in the constant pool, and reference A is stored in the constant pool and returned to S. At this point String(“hello”).intern() will return A reference to the constant pool
    String one = "hello";
    String two = new String("hello");
    String three = one.intern();
    System.out.println(two == one);
    System.out.println(three == one);
  result:  false// One is not equal to two; However, their char[] values refer to the same block of memory true// One and three have the same referenceCopy the code

12 Object copy problem

  • Referential objectAssignment copyIs a reference object copied,A a = new A(); A b = a;Now a and B point to objects in the same block of memory
  • Using the object.clone () method, the value is copied if the field is of a value type (primitive type), and the reference to the Object rather than the Object is copied if the field is of a reference type
    @Getter
    static class A implements Cloneable{
        private B b; 
        private int index;
        public A() { b = new B(); index = 1000;  }  public A clone()throws CloneNotSupportedException{ return (A)super.clone(); } } static class B{ } public static void main(String[] args) throws Exception{  A a = new A();  A copyA = a.clone();  System.out.println( a.getIndex() == copyA.getIndex() );  System.out.println( a.getB() == copyA.getB() ); } Copy the code
    // Return the resulttrueThe reference type simply copies the reference valuetrue
    true
    Copy the code
  • Deep copy: Override clone method with serialized copy (note that Cloneable, Serializable is required)
    public A clone() throws CloneNotSupportedException {
            try {
                ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
                ObjectOutputStream out = new ObjectOutputStream(byteOut);
                out.writeObject(this);
     ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  ObjectInputStream inputStream = new ObjectInputStream(byteIn);  return (A) inputStream.readObject();  } catch (Exception e) {  e.printStackTrace();  throw new CloneNotSupportedException(e.getLocalizedMessage());  }  } Copy the code

Pay attention to the public number, communicate together


Refer to the article

  • RegisterNatives in the Object class
  • Why is Finalize not recommended in Java
  • How much memory does a Java object take up?
  • The size of a Java object in memory
  • Why do you need memory alignment and a simple analysis of alignment rules
  • JVM – Anatomy of pointer compression for JAVA OBJECT headers
  • String. Intern ()