Java sun.misc.Unsafe詳解

Unsafe類在jdk 源碼的多個類中用到,這個類的提供了一些繞開JVM的更底層功能,基於它的實現能夠提升效率。可是,它是一把雙刃劍:正如它的名字所預示的那樣,它是Unsafe的,它所分配的內存須要手動free(不被GC回收)。Unsafe類,提供了JNI某些功能的簡單替代:確保高效性的同時,使事情變得更簡單。java

這篇文章主要是如下文章的整理、翻譯。c++

http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/算法

1. Unsafe API的大部分方法都是native實現,它由105個方法組成,主要包括如下幾類:編程

(1)Info相關。主要返回某些低級別的內存信息:addressSize(), pageSize()數組

(2)Objects相關。主要提供Object和它的域操縱方法:allocateInstance(),objectFieldOffset()安全

(3)Class相關。主要提供Class和它的靜態域操縱方法:staticFieldOffset(),defineClass(),defineAnonymousClass(),ensureClassInitialized()服務器

(4)Arrays相關。數組操縱方法:arrayBaseOffset(),arrayIndexScale()數據結構

(5)Synchronization相關。主要提供低級別同步原語(如基於CPU的CAS(Compare-And-Swap)原語):monitorEnter(),tryMonitorEnter(),monitorExit(),compareAndSwapInt(),putOrderedInt()併發

(6)Memory相關。直接內存訪問方法(繞過JVM堆直接操縱本地內存):allocateMemory(),copyMemory(),freeMemory(),getAddress(),getInt(),putInt()app

2. Unsafe類實例的獲取

Unsafe類設計只提供給JVM信任的啓動類加載器所使用,是一個典型的單例模式類。它的實例獲取方法以下:

public static Unsafe getUnsafe() {
    Class cc = sun.reflect.Reflection.getCallerClass(2);
    if (cc.getClassLoader() != null)
        throw new SecurityException("Unsafe");
    return theUnsafe;
}

非啓動類加載器直接調用Unsafe.getUnsafe()方法會拋出SecurityException(具體緣由涉及JVM類的雙親加載機制)。

解決辦法有兩個,其一是經過JVM參數-Xbootclasspath指定要使用的類爲啓動類,另一個辦法就是java反射了。

Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);

經過將private單例實例暴力設置accessible爲true,而後經過Field的get方法,直接獲取一個Object強制轉換爲Unsafe。在IDE中,這些方法會被標誌爲Error,能夠經過如下設置解決:

Preferences -> Java -> Compiler -> Errors/Warnings ->
Deprecated and restricted API -> Forbidden reference -> Warning
3. Unsafe類「有趣」的應用場景

(1)繞過類初始化方法。當你想要繞過對象構造方法、安全檢查器或者沒有public的構造方法時,allocateInstance()方法變得很是有用。

class A {
    private long a; // not initialized value
 
    public A() {
        this.a = 1; // initialization
    }
 
    public long a() { return this.a; }
}

如下是構造方法、反射方法和allocateInstance()的對照

A o1 = new A(); // constructor
o1.a(); // prints 1
 
A o2 = A.class.newInstance(); // reflection
o2.a(); // prints 1
 
A o3 = (A) unsafe.allocateInstance(A.class); // unsafe
o3.a(); // prints 0

allocateInstance()根本沒有進入構造方法,在單例模式時,咱們彷佛看到了危機。

(2)內存修改

內存修改在c語言中是比較常見的,在Java中,能夠用它繞過安全檢查器。

考慮如下簡單准入檢查規則:

class Guard {
    private int ACCESS_ALLOWED = 1;
 
    public boolean giveAccess() {
        return 42 == ACCESS_ALLOWED;
    }
}

在正常狀況下,giveAccess總會返回false,但事情不老是這樣

Guard guard = new Guard();
guard.giveAccess();   // false, no access
 
// bypass
Unsafe unsafe = getUnsafe();
Field f = guard.getClass().getDeclaredField("ACCESS_ALLOWED");
unsafe.putInt(guard, unsafe.objectFieldOffset(f), 42); // memory corruption
 
guard.giveAccess(); // true, access granted

經過計算內存偏移,並使用putInt()方法,類的ACCESS_ALLOWED被修改。在已知類結構的時候,數據的偏移老是能夠計算出來(與c++中的類中數據的偏移計算是一致的)。

(3)實現相似C語言的sizeOf()函數

經過結合Java反射和objectFieldOffset()函數實現一個C-like sizeOf()函數。

public static long sizeOf(Object o) {
    Unsafe u = getUnsafe();
    HashSet fields = new HashSet();
    Class c = o.getClass();
    while (c != Object.class) {
        for (Field f : c.getDeclaredFields()) {
            if ((f.getModifiers() & Modifier.STATIC) == 0) {
                fields.add(f);
            }
        }
        c = c.getSuperclass();
    }
 
    // get offset
    long maxSize = 0;
    for (Field f : fields) {
        long offset = u.objectFieldOffset(f);
        if (offset > maxSize) {
            maxSize = offset;
        }
    }
 
    return ((maxSize/8) + 1) * 8;   // padding
}

算法的思路很是清晰:從底層子類開始,依次取出它本身和它的全部超類的非靜態域,放置到一個HashSet中(重複的只計算一次,Java是單繼承),而後使用objectFieldOffset()得到一個最大偏移,最後還考慮了對齊。

在32位的JVM中,能夠經過讀取class文件偏移爲12的long來獲取size。

public static long sizeOf(Object object){
    return getUnsafe().getAddress(
        normalize(getUnsafe().getInt(object, 4L)) + 12L);
}

其中normalize()函數是一個將有符號int轉爲無符號long的方法

private static long normalize(int value) {
    if(value >= 0) return value;
    return (0L >>> 32) & value;
}

兩個sizeOf()計算的類的尺寸是一致的。最標準的sizeOf()實現是使用java.lang.instrument,可是,它須要指定命令行參數-javaagent。

(4)實現Java淺複製

標準的淺複製方案是實現Cloneable接口或者本身實現的複製函數,它們都不是多用途的函數。經過結合sizeOf()方法,能夠實現淺複製。

static Object shallowCopy(Object obj) {
    long size = sizeOf(obj);
    long start = toAddress(obj);
    long address = getUnsafe().allocateMemory(size);
    getUnsafe().copyMemory(start, address, size);
    return fromAddress(address);
}

如下的toAddress()和fromAddress()分別將對象轉換到它的地址以及相反操做。

static long toAddress(Object obj) {
    Object[] array = new Object[] {obj};
    long baseOffset = getUnsafe().arrayBaseOffset(Object[].class);
    return normalize(getUnsafe().getInt(array, baseOffset));
}
 
static Object fromAddress(long address) {
    Object[] array = new Object[] {null};
    long baseOffset = getUnsafe().arrayBaseOffset(Object[].class);
    getUnsafe().putLong(array, baseOffset, address);
    return array[0];
}

以上的淺複製函數能夠應用於任意java對象,它的尺寸是動態計算的。

(5)消去內存中的密碼

密碼字段存儲在String中,可是,String的回收是受到JVM管理的。最安全的作法是,在密碼字段使用完以後,將它的值覆蓋。

Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
char[] mem = (char[]) stringValue.get(password);
for (int i=0; i < mem.length; i++) {
  mem[i] = '?';
}

(6)動態加載類

標準的動態加載類的方法是Class.forName()(在編寫jdbc程序時,記憶深入),使用Unsafe也能夠動態加載java 的class文件。

byte[] classContents = getClassContent();
Class c = getUnsafe().defineClass(
              null, classContents, 0, classContents.length);
    c.getMethod("a").invoke(c.newInstance(), null); // 1
getClassContent()方法,將一個class文件,讀取到一個byte數組。
 
private static byte[] getClassContent() throws Exception {
    File f = new File("/home/mishadoff/tmp/A.class");
    FileInputStream input = new FileInputStream(f);
    byte[] content = new byte[(int)f.length()];
    input.read(content);
    input.close();
    return content;
}

動態加載、代理、切片等功能中能夠應用。

(7)包裝受檢異常爲運行時異常。

getUnsafe().throwException(new IOException());

當你不但願捕獲受檢異常時,能夠這樣作(並不推薦)。

(8)快速序列化

標準的java Serializable速度很慢,它還限制類必須有public無參構造函數。Externalizable好些,它須要爲要序列化的類指定模式。流行的高效序列化庫,好比kryo依賴於第三方庫,會增長內存的消耗。能夠經過getInt(),getLong(),getObject()等方法獲取類中的域的實際值,將類名稱等信息一塊兒持久化到文件。kryo有使用Unsafe的嘗試,可是沒有具體的性能提高的數據。(http://code.google.com/p/kryo/issues/detail?id=75)

(9)在非Java堆中分配內存

使用java 的new會在堆中爲對象分配內存,而且對象的生命週期內,會被JVM GC管理。

class SuperArray {
    private final static int BYTE = 1;
 
    private long size;
    private long address;
 
    public SuperArray(long size) {
        this.size = size;
        address = getUnsafe().allocateMemory(size * BYTE);
    }
 
    public void set(long i, byte value) {
        getUnsafe().putByte(address + i * BYTE, value);
    }
 
    public int get(long idx) {
        return getUnsafe().getByte(address + idx * BYTE);
    }
 
    public long size() {
        return size;
    }
}

Unsafe分配的內存,不受Integer.MAX_VALUE的限制,而且分配在非堆內存,使用它時,須要很是謹慎:忘記手動回收時,會產生內存泄露;非法的地址訪問時,會致使JVM崩潰。在須要分配大的連續區域、實時編程(不能容忍JVM延遲)時,可使用它。java.nio使用這一技術。

(10)Java併發中的應用

經過使用Unsafe.compareAndSwap()能夠用來實現高效的無鎖數據結構。

class CASCounter implements Counter {
    private volatile long counter = 0;
    private Unsafe unsafe;
    private long offset;

    public CASCounter() throws Exception {
        unsafe = getUnsafe();
        offset = unsafe.objectFieldOffset(CASCounter.class.getDeclaredField("counter"));
    }

    @Override
    public void increment() {
        long before = counter;
        while (!unsafe.compareAndSwapLong(this, offset, before, before + 1)) {
            before = counter;
        }
    }

    @Override
    public long getCounter() {
        return counter;
    }
}

經過測試,以上數據結構與java的原子變量的效率基本一致,Java原子變量也使用Unsafe的compareAndSwap()方法,而這個方法最終會對應到cpu的對應原語,所以,它的效率很是高。這裏有一個實現無鎖HashMap的方案(http://www.azulsystems.com/about_us/presentations/lock-free-hash ,這個方案的思路是:分析各個狀態,建立拷貝,修改拷貝,使用CAS原語,自旋鎖),在普通的服務器機器(核心<32),使用ConcurrentHashMap(JDK8之前,默認16路分離鎖實現,JDK8中ConcurrentHashMap已經使用無鎖實現)明顯已經夠用。

//下面是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 (tromey@redhat.com)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 */
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 #putObjectVolatile(Object,long,Object)
   */
  public native void putObject(Object obj, long offset, Object value);
  /***
   * Retrieves the value of the object field at the specified offset in the
   * supplied object with volatile load semantics.
   * 獲取obj對象中offset偏移地址對應的object型field的值,支持volatile load語義。
   * 
   * @param obj the object containing the field to read.
   *    包含須要去讀取的field的對象
   * @param offset the offset of the object field within <code>obj</code>.
   *       <code>obj</code>中object型field的偏移量
   */
  public native Object getObjectVolatile(Object obj, long offset);
  /***
   * Returns the offset of the first element for a given array class.
   * To access elements of the array class, this value may be used along with
   * with that returned by 
   * <a href="#arrayIndexScale"><code>arrayIndexScale</code></a>,
   * if non-zero.
   * 獲取給定數組中第一個元素的偏移地址。
   * 爲了存取數組中的元素,這個偏移地址與<a href="#arrayIndexScale"><code>arrayIndexScale
   * </code></a>方法的非0返回值一塊兒被使用。
   * @param arrayClass the class for which the first element's address should
   *                   be obtained.
   *                   第一個元素地址被獲取的class
   * @return the offset of the first element of the array class.
   *    數組第一個元素 的偏移地址
   * @see arrayIndexScale(Class)
   */
  public native int arrayBaseOffset(Class arrayClass);
  /***
   * Returns the scale factor used for addressing elements of the supplied
   * array class.  Where a suitable scale factor can not be returned (e.g.
   * for primitive types), zero should be returned.  The returned value
   * can be used with 
   * <a href="#arrayBaseOffset"><code>arrayBaseOffset</code></a>
   * to access elements of the class.
   * 獲取用戶給定數組尋址的換算因子.一個合適的換算因子不能返回的時候(例如:基本類型),
   * 返回0.這個返回值可以與<a href="#arrayBaseOffset"><code>arrayBaseOffset</code>
   * </a>一塊兒使用去存取這個數組class中的元素
   * 
   * @param arrayClass the class whose scale factor should be returned.
   * @return the scale factor, or zero if not supported for this array class.
   */
  public native int arrayIndexScale(Class arrayClass);

  /***
   * Releases the block on a thread created by 
   * <a href="#park"><code>park</code></a>.  This method can also be used
   * to terminate a blockage caused by a prior call to <code>park</code>.
   * This operation is unsafe, as the thread must be guaranteed to be
   * live.  This is true of Java, but not native code.
   * 釋放被<a href="#park"><code>park</code></a>建立的在一個線程上的阻塞.這個
   * 方法也能夠被使用來終止一個先前調用<code>park</code>致使的阻塞.
   * 這個操做操做時不安全的,所以線程必須保證是活的.這是java代碼不是native代碼。
   * @param thread the thread to unblock.
   *           要解除阻塞的線程
   */
  public native void unpark(Thread thread);
  /***
   * Blocks the thread until a matching 
   * <a href="#unpark"><code>unpark</code></a> occurs, the thread is
   * interrupted or the optional timeout expires.  If an <code>unpark</code>
   * call has already occurred, this also counts.  A timeout value of zero
   * is defined as no timeout.  When <code>isAbsolute</code> is
   * <code>true</code>, the timeout is in milliseconds relative to the
   * epoch.  Otherwise, the value is the number of nanoseconds which must
   * occur before timeout.  This call may also return spuriously (i.e.
   * for no apparent reason).
   * 阻塞一個線程直到<a href="#unpark"><code>unpark</code></a>出現、線程
   * 被中斷或者timeout時間到期。若是一個<code>unpark</code>調用已經出現了,
   * 這裏只計數。timeout爲0表示永不過時.當<code>isAbsolute</code>爲true時,
   * timeout是相對於新紀元以後的毫秒。不然這個值就是超時前的納秒數。這個方法執行時
   * 也可能不合理地返回(沒有具體緣由)
   * 
   * @param isAbsolute true if the timeout is specified in milliseconds from
   *                   the epoch.
   *                   若是爲true timeout的值是一個相對於新紀元以後的毫秒數
   * @param time either the number of nanoseconds to wait, or a time in
   *             milliseconds from the epoch to wait for.
   *             能夠是一個要等待的納秒數,或者是一個相對於新紀元以後的毫秒數直到
   *             到達這個時間點
   */
  public native void park(boolean isAbsolute, long time);
}
相關文章
相關標籤/搜索