//hotspot的oop.hpp文件中class oopDescclass oopDesc {
friend class VMStructs; private: volatile markOop _mark; //對象頭部分
union _metadata { // klassOop 類元數據指針
Klass* _klass;
narrowKlass _compressed_klass;
} _metadata;複製代碼
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 }
複製代碼
2^11 * 4G
。不過jvm只是將指針左移三位,所以最大範圍是2^3 * 4G = 32G
。若是大於32G,指針壓縮會失效。若是GC堆大小在4G如下,直接砍掉高32位,避免了編碼解碼過程-XX:+UseCompressedOops
(默認開啓),禁止指針壓縮:-XX:-UseCompressedOops
private static native void registerNatives()
將Object定義的本地方法和java程序連接起來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隊列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裏的默認排序順序是升序的,從小到大java
public boolean equals(Object obj) { return (this == obj);}
是使用 == 去比較的。equals方法的好處是咱們能夠重寫該方法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.javadefault 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(歸併排序)方法處理bash
Arrays.javapublic 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來排序jvm
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)
方法
Comparator提供了經常使用的幾個靜態方法thenComparing、reversed、reverseOrder(操做對象須要實現Comparator或者Comparable);可配合List.sort、Stream.sorted、Collections.sort使用。ide
@Data
@AllArgsConstructorstatic 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大小來排序oop
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存儲時,可能會存在多個咱們自定義認爲相同的對象,這樣會爲咱們代碼邏輯埋下坑。ui
Object.wait是須要在synchronized修飾的代碼內使用,會讓出CPU,並放棄對對象鎖的持有狀態。而Thread.sleep則簡單的掛起,讓出CPU,沒有釋聽任何鎖資源this
ObjectInputStream.readObject()
String one = new String("Hello");
題外話:string.intern();intern先判斷常量池是否存相同字符串,存在則返回該引用;不然在常量池中記錄堆中首次出現該字符串的引用,並返回該引用。
若是是先執行 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指向同一塊內存的對象@Getterstatic 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() );
}
@Getterstatic 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,引用類型只是複製了引用值truetrue複製代碼
深複製:重寫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());
}
}複製代碼