最近看《Java并发编程的艺术》,其中多次提到Unsafe。很有意思的一个api,从名字上看很奇怪,并且不是公开的api,只有在JDK内部才能使用。查阅了一些资料:
当然,搞Android的,少不了Android源代码:
libcore/libart/src/main/java/sun/misc/Unsafe.java
就几个我感兴趣的点研究一下:
(1)为什么叫unsafe?
Java is a safe programming language and prevents programmer from doing a lot of stupid mistakes, most of which based on memory management. But, there is a way to do such
mistakes intentionally, using
Unsafe
class.
Android源代码:
/**
* The package name notwithstanding, this class is the quasi-standard
* way for Java code to gain access to and use functionality which,
* when unsupervised, would allow one to break the pointer/type safety
* of Java.
*/
* The package name notwithstanding, this class is the quasi-standard
* way for Java code to gain access to and use functionality which,
* when unsupervised, would allow one to break the pointer/type safety
* of Java.
*/
所谓Unsafe,即提供了一些API,可以绕过Java的安全机制(基于Java类型、引用、内存管理机制,对于内存访问的严格控制),进行一些更直接、更底层的操作,显然,在经典的Java编程风格中,这些操作是不安全的。这相当于Java的后门,所以只有JDK内部才能使用。
(2)原子api
Unsafe提供的一系列cas原子api,是JDK中原子操作类的实现基础。
http://www.docjar.com/html/api/sun/misc/Unsafe.java.html 注释中对此描述较清楚:
858 /**
859 * Atomically update Java variable to <tt>x</tt> if it is currently
860 * holding <tt>expected</tt>.
861 * @return <tt>true</tt> if successful
862 */
863 public final native boolean compareAndSwapObject(Object o, long offset,
864 Object expected,
865 Object x);
866
867 /**
868 * Atomically update Java variable to <tt>x</tt> if it is currently
869 * holding <tt>expected</tt>.
870 * @return <tt>true</tt> if successful
871 */
872 public final native boolean compareAndSwapInt(Object o, long offset,
873 int expected,
874 int x);
875
876 /**
877 * Atomically update Java variable to <tt>x</tt> if it is currently
878 * holding <tt>expected</tt>.
879 * @return <tt>true</tt> if successful
880 */
881 public final native boolean compareAndSwapLong(Object o, long offset,
882 long expected,
883 long x);
(3)在安卓上如何实现的原子api?
以Unsafe.compareAndSwapInt()为例,追到native,一探究竟。
/**
* Performs a compare-and-set operation on an <code>int</code>
* field within the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within <code>obj</code>
* @param expectedValue expected value of the field
* @param newValue new value to store in the field if the contents are
* as expected
* @return <code>true</code> if the new value was in fact stored, and
* <code>false</code> if not
*/
public native boolean compareAndSwapInt(Object obj, long offset,
int expectedValue, int newValue);
显然,这是一个native method。在Android codebase中搜索native定义,发现了:
static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
jint expectedValue, jint newValue) {
ScopedFastNativeObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
// JNI must use non transactional mode.
bool success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
expectedValue, newValue);
return success ? JNI_TRUE : JNI_FALSE;
}
调用了mirror::Object的CasFieldStrongSequentiallyConsistent32(),寻找定义:
template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
int32_t old_value, int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
if (kTransactionActive) {
Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
}
if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
}
uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
}
关键调用AtomicInteger的CompareExchangeStrongSequentiallyConsistent():
// Atomically replace the value with desired value if it matches the expected value.
// Participates in total ordering of atomic operations.
bool CompareExchangeStrongSequentiallyConsistent(T expected_value, T desired_value) {
return this->compare_exchange_strong(expected_value, desired_value, std::memory_order_seq_cst);
}
这段代码出现在类
template<typename T>
class PACKED(sizeof(T)) Atomic : public std::atomic<T>
class PACKED(sizeof(T)) Atomic : public std::atomic<T>
可见,实际上使用的是std::atomic->compare_exchange_strong()
std::atomic有两个api:
compare_exchange_strong()
compare_exchange_weak()
api参考文档:
两个API基本功能是相同的
Compares the contents of the
contained value with
expected:
- if true, it replaces the contained value with val (like store).
- if false, it replaces expected with the contained value .
区别在于weak可能在满足true的情况下仍然返回false,所以只能在循环里使用,否则可以使用strong。之所以有weak版本是因为可以在某些平台上提升性能。
- if true, it replaces the contained value with val (like store).
- if false, it replaces expected with the contained value .