//hotspot的oop.hpp文件中class oopDesc class oopDesc { friend class VMStructs; private: volatile markOop _mark; //對象部分 union _metadata { // klassOop 類元數據指針 Klass* _klass; narrowKlass _compressed_klass; } _metadata;
內存對齊好處html
指針壓縮java
哪些信息會被壓縮數組
public static void main(String[] args){ Object a = new Object(); // 16B 關閉壓縮仍是16B,須要是8B倍數;12B+填充的4B int[] arr = new int[10]; // 24B 關閉壓縮則是16B } public class ObjectNum { //8B mark word //4B Klass Pointer 若是關閉壓縮則佔用8B //-XX:-UseCompressedClassPointers或-XX:-UseCompressedOops, int id; //4B String name; //4B 若是關閉壓縮則佔用8B byte b; //1B 實際內存可能會填充到4B Object o; //4B 若是關閉壓縮則佔用8B }
<br/>jvm要求對象起始位置對齊8字節的倍數,能夠利用這點提高選址範圍,理論上能夠提高到`2^11 * 4G`。不過jvm將只是指針左移三位,所以`2^3 * 4G = 32G`。若是**大於32G**,指針壓縮會失效。若是GC堆大小在 **4G如下**,直接砍掉高32位,避免了編碼解碼過程 - 啓用指針壓縮`-XX:+UseCompressedOops`(**默認開啓**),禁止指針壓縮:`-XX:-UseCompressedOops`
本地方法jvm
private static native void registerNatives()
將Object定義的本地方法和java程序連接起來。對JNI方面瞭解很少,就很少解釋了Object類中的registerNatives public final native Class<?> getClass()
獲取java的Class元數據public native int hashCode()
獲取對象的哈希Codeprotected native Object clone() throws CloneNotSupportedException
得到對象的克隆對象,淺複製public final native void notify()
喚醒等待對象鎖waitSet隊列中的一個線程public final native void notifyAll()
相似notify(),喚醒等待對象鎖waitSet隊列中的所有線程public final native void wait(long timeout)
釋放對象鎖,進入對象鎖的waitSet隊列普通方法ide
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; //都是基於native void wait(long timeout)實現的 public final void wait() throws InterruptedException; wait(long timeout, int nanos)、wait() //jvm回收對象前,會特地調用此方法 protected void finalize() throws Throwable;
如不指定排序順序,java裏的默認排序順序是升序的,從小到大oop
public boolean equals(Object obj) { return (this == obj);}
是使用 == 去比較的。equals方法的好處是咱們能夠重寫該方法Comparable.compareTo 是接口Comparable裏的抽象方法;若是對象實現該接口,可以使用Collections.sort(List< T> col)進行排序。接下來看看源碼怎麼實現的佈局
Collections.java //Collections.sort(List<T> list),調用的是List的sort方法 public static <T extends Comparable<? super T>> void sort(List<T> list) { list.sort(null); }
List的sort 則調用了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); } }
若是Comparator c 爲null,則是調用 Arrays.sort(Object[] a) ;最終調用LegacyMergeSort(歸併排序)方法處理this
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); } }
LegacyMergeSort方法裏的一段代碼;最終底層是使用歸併排序和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; }
Comparator也是一個接口,不過提供了更豐富的操做,須要實現int compare(T o1, T o2)
方法
<br/>Comparator提供了經常使用的幾個靜態方法thenComparing、reversed、reverseOrder(操做對象須要實現Comparator或者Comparable);可配合List.sort、Stream.sorted、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) {return o1.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()); col.stream().sorted(Comparator.comparing(Pair::getOne).thenComparing(Pair::getTwo)) .forEach(item -> System.out.println(item.toString()) ); }
Collections.sort默認是升序排序的,能夠看到reverseOrder將順序反過來了; 用了thenComparing的col則是先判斷Pair::getOne的大小,若是相等則判斷Pair::getTwo大小來排序
result: 4-6 4-2 1-3 ---------------- 1-3 4-2 4-6
構造方法是每個類獨有的,並不能被子類繼承,由於構造方法沒有返回值,子類定義不了和父類的構造方法同樣的方法。可是在同一個類中,構造方法能夠重載
public class TestEquals { int i; public TestEquals() { i = 0; } //構造方法重載 public TestEquals(int i) { this.i = i } }
equals是用來比較兩個對象是否相等的,能夠重寫該方法來實現自定義的比較方法;而hashCode則是用來獲取對象的哈希值,也能夠重寫該方法。當對象存儲在Map時,是首先利用Object.hashCode判斷是否映射在同一位置,若在同一映射位,則再使用equals比較兩個對象是否相同。
若是重寫equals致使對象比較相同而hashCode不同,是違反JDK規範的;並且當用HashMap存儲時,可能會存在多個咱們自定義認爲相同的對象,這樣會爲咱們代碼邏輯埋下坑。
Object.wait是須要在synchronized修飾的代碼內使用,會讓出CPU,並放棄對對象鎖的持有狀態。而Thread.sleep則簡單的掛起,讓出CPU,沒有釋聽任何鎖資源
finally和finalize區別
類似的關鍵字final
ObjectInputStream.readObject()
String one = new String("Hello");
<br/> 兩個對象和一個棧變量:一個棧變量one和一個new String()實例對象、一個"hello"字符串對象
<br/>若是是先執行 String s = "hello" ;
至關於執行了intern();先在常量池建立"hello",而且將引用A存入常量池,返回給s。此時String("hello").intern()會返回常量池的引用A返回
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雖然不等於two;可是它們具體的char[] value 仍是指向同一塊內存的 true // one 和 three 引用相同
A a = new A(); A b = a;
此時a和b指向同一塊內存的對象使用Object.clone()方法,若是字段是值類型(基本類型)則是複製該值,若是是引用類型則複製對象的引用而並不是對象
@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() ); }
//返回結果都是true,引用類型只是複製了引用值 true true
深複製:重寫clone方法時使用序列化複製,(注意須要實現Cloneable,Serializable)
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()); } }