您的位置:首页 > Web前端

关于Java Unsafe

2017-03-22 10:28 239 查看
最近看《Java并发编程的艺术》,其中多次提到Unsafe。很有意思的一个api,从名字上看很奇怪,并且不是公开的api,只有在JDK内部才能使用。查阅了一些资料:

http://www.cnblogs.com/mickole/articles/3757278.html

http://aswang.iteye.com/blog/1741871

http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
http://www.docjar.com/html/api/sun/misc/Unsafe.java.html
当然,搞Android的,少不了Android源代码:

libcore/libart/src/main/java/sun/misc/Unsafe.java

就几个我感兴趣的点研究一下:

(1)为什么叫unsafe?
http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-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 suchmistakes 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.

 */

所谓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,一探究竟。

libcore/libart/src/main/java/sun/misc/Unsafe.java:

/**
* 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定义,发现了:

art/runtime/native/sun_misc_Unsafe.cc:

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(),寻找定义:

art/runtime/mirror/object-inl.h:

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():

art/runtime/atomic.h:

// 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>

可见,实际上使用的是std::atomic->compare_exchange_strong()

std::atomic有两个api:

compare_exchange_strong()

compare_exchange_weak()

api参考文档:

http://www.cplusplus.com/reference/atomic/atomic/compare_exchange_weak/

http://www.cplusplus.com/reference/atomic/atomic/compare_exchange_strong/

两个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版本是因为可以在某些平台上提升性能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: