本文基于A(yíng)ndroid N源碼分析
前言Java最初被設計為一種安全的受控環(huán)境。盡管如此,HotSpot還是包含了一個(gè)后門(mén)sun.misc.Unsafe,提供了一些可以直接操控內存和線(xiàn)程的底層操作。Unsafe被JDK廣泛應用于java.nio和并發(fā)包等實(shí)現中,這個(gè)不安全的類(lèi)提供了一個(gè)觀(guān)察HotSpot JVM內部結構并且可以對其進(jìn)行修改,但是不建議在生產(chǎn)環(huán)境中使用。/** * A collection of methods for performing low-level, unsafe operations. * Although the class and all methods are public, use of this class is * limited because only trusted code can obtain instances of it. * * @author John R. Rose * @see #getUnsafe */執行低級、不安全操作的方法的集合,盡管類(lèi)和所有方法都是公共的,但是這個(gè)類(lèi)的使用是有限的,因為只有受信任的代碼才能獲取它的實(shí)例。這是在A(yíng)ndroid 源碼中對這個(gè)類(lèi)的注釋。
/** * Gets the unique instance of this class. This is only allowed in * very limited situations. */ public static Unsafe getUnsafe() { /* * Only code on the bootclasspath is allowed to get at the * Unsafe instance. */ ClassLoader calling = VMStack.getCallingClassLoader(); if ((calling != null) && (calling != Unsafe.class.getClassLoader())) { throw new SecurityException('Unsafe access denied'); } return THE_ONE; }通過(guò)注釋我們可以看出這個(gè)方法使用情況有限,只有在bootclasspath里面的代碼才允許運行。如果我們想使用的話(huà)也不是沒(méi)有辦法那就是反射。
在java環(huán)境
public static Unsafe getUnsafe() { try { Field f = Unsafe.class.getDeclaredField('theUnsafe'); f.setAccessible(true); return (Unsafe)f.get(null); } catch (Exception e) { /* ... */ }}android API下面無(wú)法直接獲取到Unsafe這個(gè)類(lèi)
static { try { unsafeClass = Class.forName('sun.misc.Unsafe'); if (Build.VERSION.SDK_INT >= 19) { Field theUnsafeInstance = unsafeClass.getDeclaredField('theUnsafe'); theUnsafeInstance.setAccessible(true); unsafe = theUnsafeInstance.get(null); } else { Class AQSClass = Class.forName('java.util.concurrent.locks.AbstractQueuedSynchronizer'); Field theUnsafeInstance = AQSClass.getDeclaredField('unsafe'); theUnsafeInstance.setAccessible(true); unsafe = theUnsafeInstance.get(null); } } catch (Exception e) { e.printStackTrace(); } }要在Java層操作內容,也不是沒(méi)有辦法做到;JDK給我們留了一個(gè)后門(mén):sun.misc.Unsafe 類(lèi);在OpenJDK里面這個(gè)類(lèi)灰常強大,從內存操作到CAS到鎖機制,但是在A(yíng)ndroid 平臺還有一點(diǎn)點(diǎn)不一樣,在 Android N之前,Android的JDK實(shí)現是 Apache Harmony,這個(gè)實(shí)現里面的Unsafe就有點(diǎn)雞肋了,沒(méi)法寫(xiě)內存;好在A(yíng)ndroid 又開(kāi)了一個(gè)后門(mén):Memory 類(lèi)。
java不能直接訪(fǎng)問(wèn)操作系統底層,而是通過(guò)本地方法來(lái)訪(fǎng)問(wèn)。Unsafe類(lèi)提供了硬件級別的原子操作,主要提供了以下功能:
public native long allocateMemory(long bytes);//分配內存public native void freeMemory(long address);//釋放內存public native void copyMemory(long srcAddr, long dstAddr, long bytes);//復制內存public native int addressSize();public native int pageSize();/** * Gets the offset from the start of an array object's memory to * the memory used to store its initial (zeroeth) element. * * @param clazz non-null; class in question; must be an array class * @return the offset to the initial element */ public int arrayBaseOffset(Class clazz) {} /** * Gets the size of each element of the given array class. * * @param clazz non-null; class in question; must be an array class * @return > 0; the size of each element of the array */ public int arrayIndexScale(Class clazz) {} /** * Allocates an instance of the given class without running the constructor. * The class' <clinit> will be run, if necessary. */ public native Object allocateInstance(Class<?> c); /** * Parks the calling thread for the specified amount of time, * unless the 'permit' for the thread is already available (due to * a previous call to {@link #unpark}. This method may also return * spuriously (that is, without the thread being told to unpark * and without the indicated amount of time elapsing). * * <p>See {@link java.util.concurrent.locks.LockSupport} for more * in-depth information of the behavior of this method.</p> * * @param absolute whether the given time value is absolute * milliseconds-since-the-epoch true or relative * nanoseconds-from-now false * @param time the (absolute millis or relative nanos) time value */ public void park(boolean absolute, long time) { if (absolute) { Thread.currentThread().parkUntil$(time); } else { Thread.currentThread().parkFor$(time); } } /** * Unparks the given object, which must be a {@link Thread}. * * <p>See {@link java.util.concurrent.locks.LockSupport} for more * in-depth information of the behavior of this method.</p> * * @param obj non-null; the object to unpark */ public void unpark(Object obj) { if (obj instanceof Thread) { ((Thread) obj).unpark$(); } else { throw new IllegalArgumentException('valid for Threads only'); } } /** * Performs a compare-and-set operation on an int * field within the given object. * * @param obj non-null; object containing the field * @param offset offset to the field within obj * @param expectedValue expected value of the field * @param newValue new value to store in the field if the contents are * as expected * @return true if the new value was in fact stored, and * false if not */ public native boolean compareAndSwapInt(Object obj, long offset, int expectedValue, int newValue);聯(lián)系客服