您的位置:首页 > 编程语言 > Java开发

jdk 源码分析(10)java unsafe 分析

2017-08-03 21:37 537 查看
jdk里面原子操作unsafe都是native方法,看不到源代码,所以特意下载openjdk 9 的版本。

1)获取unsafe 对象,这个是openjdk里的方法。通过反射获得。

static {

Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");

}

[/code]

@CallerSensitive

public static Unsafe getUnsafe() {

Class<?> caller = Reflection.getCallerClass();

if (!VM.isSystemDomainLoader(caller.getClassLoader()))

throw new SecurityException("Unsafe");

return theUnsafe;

}

[/code]

所以需要使用时直接

private static final Unsafe unsafe = Unsafe.getUnsafe();


unsafe 对象主要包括1)内存管理

public native long allocateMemory(long var1);

public native long reallocateMemory(long var1, long var3);

public native void setMemory(Object var1, long var2, long var4, byte var6);


2)对象cas,这个是乐观锁,如果变量没有被其他线程改变的话。会一直尝试去修改变量。直到变成修改值。等会将分析一下源代码。c语言的。

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);


这里的参数是,对象,偏移量,期望值,修改值。

获取偏移量的方法:

valueOffset = unsafe.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));


还有:

public native long staticFieldOffset(Field var1);

public native long objectFieldOffset(Field var1);

public native Object staticFieldBase(Field var1);


3)supportlock

public native void unpark(Object var1);

public native void park(boolean var1, long var2);


park类似于wait,unpark类似于notify。

4)cas 源码分析

具体见unsafe.cpp (版本: openjdk 9 )

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSetInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {

oop p = JNIHandles::resolve(obj);

//获取对象的变量的地址

jint* addr = (jint *)index_oop_from_field_offset_long(p, offset);

//调用Atomic操作


return (jint)(Atomic::cmpxchg(x, addr, e)) == e;

} UNSAFE_END

[/code]

进入atomic.hpp,大意就是先去获取一次结果,如果结果和现在不同,就直接返回,因为有其他人修改了;否则会一直尝试去修改。直到成功。

inline jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest,

jbyte compare_value, cmpxchg_memory_order order) {

STATIC_ASSERT(sizeof(jbyte) == 1);

volatile jint* dest_int =

static_cast<volatile jint*>(align_ptr_down(dest, sizeof(jint)));

size_t offset = pointer_delta(dest, dest_int, 1);

jint cur = *dest_int;

jbyte* cur_as_bytes = reinterpret_cast<jbyte*>(&cur);


// current value may not be what we are looking for, so force it

// to that value so the initial cmpxchg will fail if it is different

cur_as_bytes[offset] = compare_value;


// always execute a real cmpxchg so that we get the required memory

// barriers even on initial failure

do {

// value to swap in matches current value ...

jint new_value = cur;

// ... except for the one jbyte we want to update

reinterpret_cast<jbyte*>(&new_value)[offset] = exchange_value;


jint res = cmpxchg(new_value, dest_int, cur, order);

if (res == cur) break; // success


// at least one jbyte in the jint changed value, so update

// our view of the current jint

cur = res;

// if our jbyte is still as cur we loop and try again

} while (cur_as_bytes[offset] == compare_value);


return cur_as_bytes[offset];

}

[/code]

unsafe.cpp 里面 还包含很多其他的方法的实现,就不再这里分析了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jdk 源代码