关于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
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 注释中对此描述较清楚:
(3)在安卓上如何实现的原子api?
以Unsafe.compareAndSwapInt()为例,追到native,一探究竟。
libcore/libart/src/main/java/sun/misc/Unsafe.java:
显然,这是一个native method。在Android codebase中搜索native定义,发现了:
art/runtime/native/sun_misc_Unsafe.cc:
调用了mirror::Object的CasFieldStrongSequentiallyConsistent32(),寻找定义:
art/runtime/mirror/object-inl.h:
关键调用AtomicInteger的CompareExchangeStrongSequentiallyConsistent():
art/runtime/atomic.h:
这段代码出现在类
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版本是因为可以在某些平台上提升性能。
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
Unsafeclass.
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版本是因为可以在某些平台上提升性能。
相关文章推荐
- 关于Java类设计中信息隐蔽原则的一点提示
- 有关于JAVA中的CLASSPATH的作用
- 关于Java异常处理的学习代码
- 关于java 的 Classpath全解
- 关于java运行环境的配置
- 关于把 java 程序编译成 exe 文件
- 关于Java和.Net,持续更新中
- 关于Java继承一个值得思考的问题。
- [征求意见]关于增加Java技术区
- JAVA与C++::关于JNI中文字符串操作问题总结
- Java中几个关于日期计算的问题
- 关于JAVA1.2与1.4考试的区别!
- 关于JAVA的分页查询操作技术
- 关于CLR Loader和Java Class Loader的讨论
- 关于C++&Java中命令行编译的问题
- 关于Java的RMI编程的一个简单的例子
- 今日的问题:关于java.util包的几个问题?
- 关于JAVA的分页查询操作技术(zz)
- 关于JAVA匿名内部类,回调,事件模式的一点讨论 VS dotNET事件模式
- 关于Java的Classloader的讨论收获