java不能直接訪問操做系統底層,而是經過本地方法來訪問。Unsafe類提供了硬件級別的原子操做,主要提供瞭如下功能:java
一、經過Unsafe類能夠分配內存,能夠釋放內存;數組
類中提供的3個本地方法allocateMemory、reallocateMemory、freeMemory分別用於分配內存,擴充內存和釋放內存,與C語言中的3個方法對應。併發
public native long allocateMemory(long l); public native long reallocateMemory(long l, long l1); public native void freeMemory(long l);
二、能夠定位對象某字段的內存位置,也能夠修改對象的字段值,即便它是私有的;框架
字段的定位:操作系統
JAVA中對象的字段的定位可能經過staticFieldOffset方法實現,該方法返回給定field的內存地址偏移量,這個值對於給定的filed是惟一的且是固定不變的。線程
getIntVolatile方法獲取對象中offset偏移地址對應的整型field的值,支持volatile load語義。對象
getLong方法獲取對象中offset偏移地址對應的long型field的值內存
數組元素定位:get
Unsafe類中有不少以BASE_OFFSET結尾的常量,好比ARRAY_INT_BASE_OFFSET,ARRAY_BYTE_BASE_OFFSET等,這些常量值是經過arrayBaseOffset方法獲得的。arrayBaseOffset方法是一個本地方法,能夠獲取數組第一個元素的偏移地址。Unsafe類中還有不少以INDEX_SCALE結尾的常量,好比 ARRAY_INT_INDEX_SCALE , ARRAY_BYTE_INDEX_SCALE等,這些常量值是經過arrayIndexScale方法獲得的。arrayIndexScale方法也是一個本地方法,能夠獲取數組的轉換因子,也就是數組中元素的增量地址。將arrayBaseOffset與arrayIndexScale配合使用,能夠定位數組中每一個元素在內存中的位置。class
Arrays和Java別的對象同樣,都有一個對象頭,它是存儲在實際的數據前面的。這個頭的長度能夠經過unsafe.arrayBaseOffset(T[].class)方法來獲取到,這裏T是數組元素的類型。數組元素的大小能夠經過unsafe.arrayIndexScale(T[].class) 方法獲取到。這也就是說要訪問類型爲T的第N個元素的話,你的偏移量offset應該是arrayOffset+N*arrayScale。
public final class Unsafe { public static final int ARRAY_INT_BASE_OFFSET; public static final int ARRAY_INT_INDEX_SCALE; public native long staticFieldOffset(Field field); public native int getIntVolatile(Object obj, long l); public native long getLong(Object obj, long l); public native int arrayBaseOffset(Class class1); public native int arrayIndexScale(Class class1); static { ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset([I); ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale([I); } }
三、掛起與恢復
將一個線程進行掛起是經過park方法實現的,調用 park後,線程將一直阻塞直到超時或者中斷等條件出現。unpark能夠終止一個掛起的線程,使其恢復正常。整個併發框架中對線程的掛起操做被封裝在 LockSupport類中,LockSupport類中有各類版本pack方法,但最終都調用了Unsafe.park()方法。
public class LockSupport { public static void unpark(Thread thread) { if (thread != null) unsafe.unpark(thread); } public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); unsafe.park(false, 0L); setBlocker(t, null); } public static void parkNanos(Object blocker, long nanos) { if (nanos > 0) { Thread t = Thread.currentThread(); setBlocker(t, blocker); unsafe.park(false, nanos); setBlocker(t, null); } } public static void parkUntil(Object blocker, long deadline) { Thread t = Thread.currentThread(); setBlocker(t, blocker); unsafe.park(true, deadline); setBlocker(t, null); } public static void park() { unsafe.park(false, 0L); } public static void parkNanos(long nanos) { if (nanos > 0) unsafe.park(false, nanos); } public static void parkUntil(long deadline) { unsafe.park(true, deadline); } }
四、CAS操做
是經過compareAndSwapXXX方法實現的
/** * 比較obj的offset處內存位置中的值和指望的值,若是相同則更新。此更新是不可中斷的。 * * @param obj 須要更新的對象 * @param offset obj中整型field的偏移量 * @param expect 但願field中存在的值 * @param update 若是指望值expect與field的當前值相同,設置filed的值爲這個新值 * @return 若是field的值被更改返回true */ public native boolean compareAndSwapInt(Object obj, long offset, int expect, int update);
CAS操做有3個操做數,內存值M,預期值E,新值U,若是M==E,則將內存值修改成B,不然啥都不作。