//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()); } }