【Java深入研究】8、Java中Unsafe類詳解,深入研究unsafe
java不能直接存取作業系統底層,而是通過本地方法來訪問。Unsafe類提供了硬體層級的原子操作,主要提供了以下功能:
1、通過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);
2、可以定位對象某欄位的記憶體位置,也可以修改對象的欄位值,即使它是私人的;
欄位的定位:
JAVA中對象的欄位的定位可能通過staticFieldOffset方法實現,該方法返回給定field的記憶體位址位移量,這個值對於給定的filed是唯一的且是固定不變的。
getIntVolatile方法擷取對象中offset位移地址對應的整型field的值,支援volatile load語義。
getLong方法擷取對象中offset位移地址對應的long型field的值
數組元素定位:
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配合使用,可以定位元組中每個元素在記憶體中的位置。
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); }}3、掛起與恢複
將一個線程進行掛起是通過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); }}
4、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,否則啥都不做。