Unsafe--Java中Unsafe類詳解
java不能直接訪問作業系統底層,而是通過本地方法來訪問。Unsafe類提供了硬體級別的原子操作,主要提供了以下功能:
1、通過Unsafe類可以分配記憶體,可以釋放記憶體;
類中提供的3個本地方法allocateMemory、reallocateMemory、freeMemory分別用於分配記憶體,擴充記憶體和釋放記憶體,與C語言中的3個方法對應。
2、可以定位物件某欄位的記憶體位置,也可以修改物件的欄位值,即使它是私有的;
public native long allocateMemory(long l); public native long reallocateMemory(longl, long l1); public native void freeMemory(long l);
欄位的定位:
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,否則啥都不做。
參考資料:
首先介紹一下什麼是Compare And Swap(CAS)?簡單的說就是比較並交換。
CAS 操作包含三個運算元 —— 記憶體位置(V)、預期原值(A)和新值(B)。如果記憶體位置的值與預期原值相匹配,那麼處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會在 CAS 指令之前返回該位置的值。CAS 有效地說明了“我認為位置 V 應該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置現在的值即可。” Java併發包(java.util.concurrent)中大量使用了CAS操作,涉及到併發的地方都呼叫了sun.misc.Unsafe類方法進行CAS操作。
在看一下volatile, Volatile修飾的成員變數在每次被執行緒訪問時,都強迫從共享記憶體中重讀該成員變數的值。而且,當成員變數發生變化時,強迫執行緒將變化值回寫到共享記憶體。這樣在任何時刻,兩個不同的執行緒總是看到某個成員變數的值是相同的,更簡單一點理解就是volatile修飾的變數值發生變化時對於另外的執行緒是可見的。
如何正確使用volatile可以參考下面這篇文章:
下面來看看java中具體的CAS操作類sun.misc.Unsafe。Unsafe類提供了硬體級別的原子操作,Java無法直接訪問到作業系統底層(如系統硬體等),為此Java使用native方法來擴充套件Java程式的功能。具體實現使用c++,詳見檔案sun.misc.natUnsafe.cc();sun.misc包的原始碼可以在這裡找到:
//下面是sun.misc.Unsafe.java類原始碼 package sun.misc; import java.lang.reflect.Field; /*** * This class should provide access to low-level operations and its * use should be limited to trusted code. Fields can be accessed using * memory addresses, with undefined behaviour occurring if invalid memory * addresses are given. * 這個類提供了一個更底層的操作並且應該在受信任的程式碼中使用。可以通過記憶體地址 * 存取fields,如果給出的記憶體地址是無效的那麼會有一個不確定的執行表現。 * * @author Tom Tromey ([email protected]) * @author Andrew John Hughes ([email protected]) */ public class Unsafe { // Singleton class. private static Unsafe unsafe = new Unsafe(); /*** * Private default constructor to prevent creation of an arbitrary * number of instances. * 使用私有預設構造器防止建立多個例項 */ private Unsafe() { } /*** * Retrieve the singleton instance of <code>Unsafe</code>. The calling * method should guard this instance from untrusted code, as it provides * access to low-level operations such as direct memory access. * 獲取<code>Unsafe</code>的單例,這個方法呼叫應該防止在不可信的程式碼中例項, * 因為unsafe類提供了一個低級別的操作,例如直接記憶體存取。 * * @throws SecurityException if a security manager exists and prevents * access to the system properties. * 如果安全管理器不存在或者禁止訪問系統屬性 */ public static Unsafe getUnsafe() { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPropertiesAccess(); return unsafe; } /*** * Returns the memory address offset of the given static field. * The offset is merely used as a means to access a particular field * in the other methods of this class. The value is unique to the given * field and the same value should be returned on each subsequent call. * 返回指定靜態field的記憶體地址偏移量,在這個類的其他方法中這個值只是被用作一個訪問 * 特定field的一個方式。這個值對於 給定的field是唯一的,並且後續對該方法的呼叫都應該 * 返回相同的值。 * * @param field the field whose offset should be returned. * 需要返回偏移量的field * @return the offset of the given field. * 指定field的偏移量 */ public native long objectFieldOffset(Field field); /*** * Compares the value of the integer field at the specified offset * in the supplied object with the given expected value, and updates * it if they match. The operation of this method should be atomic, * thus providing an uninterruptible way of updating an integer field. * 在obj的offset位置比較integer field和期望的值,如果相同則更新。這個方法 * 的操作應該是原子的,因此提供了一種不可中斷的方式更新integer field。 * * @param obj the object containing the field to modify. * 包含要修改field的物件 * @param offset the offset of the integer field within <code>obj</code>. * <code>obj</code>中整型field的偏移量 * @param expect the expected value of the field. * 希望field中存在的值 * @param update the new value of the field if it equals <code>expect</code>. * 如果期望值expect與field的當前值相同,設定filed的值為這個新值 * @return true if the field was changed. * 如果field的值被更改 */ public native boolean compareAndSwapInt(Object obj, long offset, int expect, int update); /*** * Compares the value of the long field at the specified offset * in the supplied object with the given expected value, and updates * it if they match. The operation of this method should be atomic, * thus providing an uninterruptible way of updating a long field. * 在obj的offset位置比較long field和期望的值,如果相同則更新。這個方法 * 的操作應該是原子的,因此提供了一種不可中斷的方式更新long field。 * * @param obj the object containing the field to modify. * 包含要修改field的物件 * @param offset the offset of the long field within <code>obj</code>. * <code>obj</code>中long型field的偏移量 * @param expect the expected value of the field. * 希望field中存在的值 * @param update the new value of the field if it equals <code>expect</code>. * 如果期望值expect與field的當前值相同,設定filed的值為這個新值 * @return true if the field was changed. * 如果field的值被更改 */ public native boolean compareAndSwapLong(Object obj, long offset, long expect, long update); /*** * Compares the value of the object field at the specified offset * in the supplied object with the given expected value, and updates * it if they match. The operation of this method should be atomic, * thus providing an uninterruptible way of updating an object field. * 在obj的offset位置比較object field和期望的值,如果相同則更新。這個方法 * 的操作應該是原子的,因此提供了一種不可中斷的方式更新object field。 * * @param obj the object containing the field to modify. * 包含要修改field的物件 * @param offset the offset of the object field within <code>obj</code>. * <code>obj</code>中object型field的偏移量 * @param expect the expected value of the field. * 希望field中存在的值 * @param update the new value of the field if it equals <code>expect</code>. * 如果期望值expect與field的當前值相同,設定filed的值為這個新值 * @return true if the field was changed. * 如果field的值被更改 */ public native boolean compareAndSwapObject(Object obj, long offset, Object expect, Object update); /*** * Sets the value of the integer field at the specified offset in the * supplied object to the given value. This is an ordered or lazy * version of <code>putIntVolatile(Object,long,int)</code>, which * doesn't guarantee the immediate visibility of the change to other * threads. It is only really useful where the integer field is * <code>volatile</code>, and is thus expected to change unexpectedly. * 設定obj物件中offset偏移地址對應的整型field的值為指定值。這是一個有序或者 * 有延遲的<code>putIntVolatile</cdoe>方法,並且不保證值的改變被其他執行緒立 * 即看到。只有在field被<code>volatile</code>修飾並且期望被意外修改的時候 * 使用才有用。 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the integer field within <code>obj</code>. * <code>obj</code>中整型field的偏移量 * @param value the new value of the field. * field將被設定的新值 * @see #putIntVolatile(Object,long,int) */ public native void putOrderedInt(Object obj, long offset, int value); /*** * Sets the value of the long field at the specified offset in the * supplied object to the given value. This is an ordered or lazy * version of <code>putLongVolatile(Object,long,long)</code>, which * doesn't guarantee the immediate visibility of the change to other * threads. It is only really useful where the long field is * <code>volatile</code>, and is thus expected to change unexpectedly. * 設定obj物件中offset偏移地址對應的long型field的值為指定值。這是一個有序或者 * 有延遲的<code>putLongVolatile</cdoe>方法,並且不保證值的改變被其他執行緒立 * 即看到。只有在field被<code>volatile</code>修飾並且期望被意外修改的時候 * 使用才有用。 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the long field within <code>obj</code>. * <code>obj</code>中long型field的偏移量 * @param value the new value of the field. * field將被設定的新值 * @see #putLongVolatile(Object,long,long) */ public native void putOrderedLong(Object obj, long offset, long value); /*** * Sets the value of the object field at the specified offset in the * supplied object to the given value. This is an ordered or lazy * version of <code>putObjectVolatile(Object,long,Object)</code>, which * doesn't guarantee the immediate visibility of the change to other * threads. It is only really useful where the object field is * <code>volatile</code>, and is thus expected to change unexpectedly. * 設定obj物件中offset偏移地址對應的object型field的值為指定值。這是一個有序或者 * 有延遲的<code>putObjectVolatile</cdoe>方法,並且不保證值的改變被其他執行緒立 * 即看到。只有在field被<code>volatile</code>修飾並且期望被意外修改的時候 * 使用才有用。 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the object field within <code>obj</code>. * <code>obj</code>中long型field的偏移量 * @param value the new value of the field. * field將被設定的新值 */ public native void putOrderedObject(Object obj, long offset, Object value); /*** * Sets the value of the integer field at the specified offset in the * supplied object to the given value, with volatile store semantics. * 設定obj物件中offset偏移地址對應的整型field的值為指定值。支援volatile store語義 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the integer field within <code>obj</code>. * <code>obj</code>中整型field的偏移量 * @param value the new value of the field. * field將被設定的新值 */ public native void putIntVolatile(Object obj, long offset, int value); /*** * Retrieves the value of the integer field at the specified offset in the * supplied object with volatile load semantics. * 獲取obj物件中offset偏移地址對應的整型field的值,支援volatile load語義。 * * @param obj the object containing the field to read. * 包含需要去讀取的field的物件 * @param offset the offset of the integer field within <code>obj</code>. * <code>obj</code>中整型field的偏移量 */ public native int getIntVolatile(Object obj, long offset); /*** * Sets the value of the long field at the specified offset in the * supplied object to the given value, with volatile store semantics. * 設定obj物件中offset偏移地址對應的long型field的值為指定值。支援volatile store語義 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the long field within <code>obj</code>. * <code>obj</code>中long型field的偏移量 * @param value the new value of the field. * field將被設定的新值 * @see #putLong(Object,long,long) */ public native void putLongVolatile(Object obj, long offset, long value); /*** * Sets the value of the long field at the specified offset in the * supplied object to the given value. * 設定obj物件中offset偏移地址對應的long型field的值為指定值。 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the long field within <code>obj</code>. * <code>obj</code>中long型field的偏移量 * @param value the new value of the field. * field將被設定的新值 * @see #putLongVolatile(Object,long,long) */ public native void putLong(Object obj, long offset, long value); /*** * Retrieves the value of the long field at the specified offset in the * supplied object with volatile load semantics. * 獲取obj物件中offset偏移地址對應的long型field的值,支援volatile load語義。 * * @param obj the object containing the field to read. * 包含需要去讀取的field的物件 * @param offset the offset of the long field within <code>obj</code>. * <code>obj</code>中long型field的偏移量 * @see #getLong(Object,long) */ public native long getLongVolatile(Object obj, long offset); /*** * Retrieves the value of the long field at the specified offset in the * supplied object. * 獲取obj物件中offset偏移地址對應的long型field的值 * * @param obj the object containing the field to read. * 包含需要去讀取的field的物件 * @param offset the offset of the long field within <code>obj</code>. * <code>obj</code>中long型field的偏移量 * @see #getLongVolatile(Object,long) */ public native long getLong(Object obj, long offset); /*** * Sets the value of the object field at the specified offset in the * supplied object to the given value, with volatile store semantics. * 設定obj物件中offset偏移地址對應的object型field的值為指定值。支援volatile store語義 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the object field within <code>obj</code>. * <code>obj</code>中object型field的偏移量 * @param value the new value of the field. * field將被設定的新值 * @see #putObject(Object,long,Object) */ public native void putObjectVolatile(Object obj, long offset, Object value); /*** * Sets the value of the object field at the specified offset in the * supplied object to the given value. * 設定obj物件中offset偏移地址對應的object型field的值為指定值。 * * @param obj the object containing the field to modify. * 包含需要修改field的物件 * @param offset the offset of the object field within <code>obj</code>. * <code>obj</code>中object型field的偏移量 * @param value the new value of the field. * field將被設定的新值 * @see相關推薦
java中String類詳解
String類 String類存在java.lang包中,專門儲存字串。是引用資料型別。 String類的兩種例項化方法 1.直接賦值 String str1= "hello"; 2.傳統賦值 Str
Java中Class類詳解、用法以及泛化
在前面我們將類的載入的時候,類載入一共有5步,載入,驗證,準備,解析和初始化。其中載入階段,除了將位元組碼載入到方法區,還生成了這個了的Java.lang.Class物件。那麼這個Class物件到底有什麼用呢? 前面的關於反射的文章,我們多次都用到了Class類,可以用這個
Java中dimension類詳解
dimension - Java的一個類 dimension是Java的一個類,封裝了一個構件的高度和寬度,這個類與一個構件的許多屬性具有相關性,因此在Component類中定義多個與之有關的方法,LayoutManager介面也與一個Dimension
Java中Number類詳解
1.資料型別基本簡介 一般情況下我們會使用資料的基本資料型別:byte、int、short、long、double、float、boolean、char; 對應的包裝型別也有八種:Byte、Integ
Java中ArrayList類詳解
1、什麼是ArrayList ArrayList就是傳說中的動態陣列,用MSDN中的說法,就是Array的複雜版本,它提供瞭如下一些好處: 動態的增加和減少元素 實現了ICollection和IList介面 靈活的設定陣列的大小 2、如何使用ArrayList
Unsafe--Java中Unsafe類詳解
java不能直接訪問作業系統底層,而是通過本地方法來訪問。Unsafe類提供了硬體級別的原子操作,主要提供了以下功能: 1、通過Unsafe類可以分配記憶體,可以釋放記憶體; 類中提供的3個本地方法allocateMemory、reallocateMemory、freeMemory分別用於分配記憶體,
java中Class物件詳解和類名.class, class.forName(), getClass()區別
package yerasel; import java.lang.reflect.Method; public class Test { /** * @param args */ public static void main(String[] args) {
java Io 流類詳解
修改 文件目錄 != exe [] 深入 clas one fileinput 關於java 流類的復習;習慣性的復習按照圖結構一層層往下深入去了解去復習,最後通過代碼來實現感覺印象會更深刻一些; 關於 I/O流:IO可以理解為JAVA用來傳遞數據的管道
Java中反射機制詳解
turn face instance java struct () 分享 2.6 一個 序言 在學習java基礎時,由於學的不紮實,講的實用性不強,就覺得沒用,很多重要的知識就那樣一筆帶過了,像這個馬上要講的反射機制一樣,當時學的時候就忽略了,到後來學習
Java中的ant詳解
問題 noi mar gin otf left 源代碼 都是 tps 分享一套幾十個源代碼,都是vc++的,打包提供 包含指針的結構數組,初始化問題 《!———— C++ 中 export 關鍵字的尷尬處境 ————》 想做一個小東西不知從何入手 493YR誒詰B駝
Java 中的resultset詳解
ins 浮點 relative 字符串類型 更新 for 變量 占用 nec 結果集(ResultSet)是數據中查詢結果返回的一種對象,可以說結果集是一個存儲查詢結果的對象,但是結果集並不僅僅具有存儲的功能,他同時還具有操縱數據的功能,可能完成對數據的更新等。 結果集
Java中jar命令詳解
做專案的時候我們肯定接觸過很多jar包,那麼jar包是什麼呢?筆者瞭解到jar是java archive file 的簡寫。從名字就可以知道,它的應用與Java息息相關。下面就詳細介紹如何自己生成jar包,這樣我們管理我們自己的程式碼(尤其是一些比較重要而且不會或者很少有修改的程式碼)。 安裝好J
Java併發工具類詳解
在JDK的併發包裡提供了幾個非常有用的併發工具類。CountDownLatch、CyclicBarrier和Semaphore工具類提供了一種併發流程控制的手段,Exchanger工具類則提供了線上程間交換資料的一種手段。本章會配合一些應用場景來介紹如何使用這些工具類。 等待多執行緒完成的Cou
Java中SimpleDateFormat用法詳解
轉自:http://blog.csdn.net/linbooooo1987/article/details/7540999 [java] view plain copy
Java中物件頭詳解
一:物件頭 HotSpot虛擬機器中,物件在記憶體中儲存的佈局可以分為三塊區域:物件頭(Header)、例項資料(Instance Data)和對齊填充(Padding)。 HotSpot虛擬機器的物件頭(Object Header)包括兩部分資訊,第一部分用於儲存物
Java中Date型別詳解
一、Date型別的初始化 1、 Date(int year, int month, int date); 直接寫入年份是得不到正確的結果的。 因為java中Date是從1900年開始算的,所以前面的第一個引數只要填入從1900年後過了多少年就是你想要得到的年份。 月需要減1,日可以直接插入。 這種方法用的比
Java中常量池詳解
在Java的記憶體分配中,總共3種常量池: 轉發連結 :https://blog.csdn.net/zm13007310400/article/details/77534349 1.字串常量池(String Constant Pool): 1.1:字串常量池在Java記憶體區域的哪個位
java 中 static 作用詳解
static表示“全域性”或者“靜態”的意思,用來修飾成員變數和成員方法,也可以形成靜態static程式碼塊,但是Java語言中沒有全域性變數的概念。 被static修飾的成員變數和成員方法獨立於該類的任何物件。也就是說,它不依賴
Java 的Properties類詳解
一、Java Properties類 Java中有個比較重要的類Properties(Java.util.Properties),主要用於讀取Java的配置檔案,各種語言都有自己所支援的配置檔案,配置檔案中很多變數是經常改變的,這樣做也是為了方便使用者,讓使
Java中的Type詳解
轉載自逆水行舟的部落格Java中的Type詳解 本文主要介紹java中Type介面的來歷以及相關的幾個介面。 通過這邊文章,我們可以瞭解到與範型相關的幾個介面, 對範型的分類有個瞭解; 還可以瞭解到Type介面與Class類的關係, 以及Type出現的原因. 反射相關介面