sun.misc.Unsafe

Unsafe在JUC里用的非常普遍,所以花时间看了看其实现, 贴先源码吧,其实并不复杂:

 sun.misc.Unsafe.java 源码:

 http://www.javasourcecode.org/html/open-source/jdk/jdk-6u23/sun/misc/Unsafe.java.html

从源码实现来看,Unsafe是个单例,其实例只能通过静态方法获得:

public static Unsafe getUnsafe() {
    Class cc = sun.reflect.Reflection.getCallerClass(2);
    if (cc.getClassLoader() != null)
        throw new SecurityException("Unsafe");
    return theUnsafe;
    }

如果我们正常的应用程序去调用的话,会抛出SecurityException,获取实例时先看调用的类是否启动类加载器加载,不是的话就抛出异常,其comment也强调Unsafe是应用于安全性代码的.那如果我们的确需要使用时,可以通过反射,将私有变量theUnsafe(唯一实例的引用)可见,再获取:

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");  
theUnsafe.setAccessible(true);  
Unsafe unsafe = (Unsafe) theUnsafe.get(null);  

Unsafe 也是基于CAS(compare and swap)的,CAS是现代CPU提供给并发程序使用的原语操作. 不同的CPU有不同的使用规范.在 Intel 处理器中,比较并交换通过指令的 cmpxchg 系列实现。CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B).JUC里的原子类的实现都是通过CAS,CAS能更高效的从机器码层面提供并发操作.

 另,相应的sun.misc.natUnsafe.cc 源码:

#include <gcj/cni.h>
#include <gcj/field.h>
#include <gcj/javaprims.h>
#include <jvm.h>
#include <sun/misc/Unsafe.h>
#include <java/lang/System.h>
#include <java/lang/InterruptedException.h>
#include <java/lang/Thread.h>
#include <java/lang/Long.h>
#include "sysdep/locks.h"


// Use a spinlock for multi-word accesses

class spinlock

{

  static volatile obj_addr_t lock;

public:

spinlock ()

  {

    while (! compare_and_swap (&lock, 0, 1))

      _Jv_ThreadYield ();

  }

  ~spinlock ()

  {

    release_set (&lock, 0);

  }

};

// This is a single lock that is used for all synchronized accesses if

// the compiler can't generate inline compare-and-swap operations.  In

// most cases it'll never be used, but the i386 needs it for 64-bit

// locked accesses and so does PPC32.  It's worth building libgcj with

// target=i486 (or above) to get the inlines.

volatile obj_addr_t spinlock::lock;

static inline bool

compareAndSwap (volatile jint *addr, jint old, jint new_val)

{

  jboolean result = false;

  spinlock lock;

  if ((result = (*addr == old)))

    *addr = new_val;

  return result;

}

static inline bool

compareAndSwap (volatile jlong *addr, jlong old, jlong new_val)

{

  jboolean result = false;

  spinlock lock;

  if ((result = (*addr == old)))

    *addr = new_val;

  return result;

}

static inline bool

compareAndSwap (volatile jobject *addr, jobject old, jobject new_val)

{

  jboolean result = false;

  spinlock lock;

  if ((result = (*addr == old)))

    *addr = new_val;

  return result;

}

jlong

sun::misc::Unsafe::objectFieldOffset (::java::lang::reflect::Field *field)

{

  _Jv_Field *fld = _Jv_FromReflectedField (field);

  // FIXME: what if it is not an instance field?

  return fld->getOffset();

}

jint

sun::misc::Unsafe::arrayBaseOffset (jclass arrayClass)

{

  // FIXME: assert that arrayClass is array.

  jclass eltClass = arrayClass->getComponentType();

  return (jint)(jlong) _Jv_GetArrayElementFromElementType (NULL, eltClass);

}

jint

sun::misc::Unsafe::arrayIndexScale (jclass arrayClass)

{

  // FIXME: assert that arrayClass is array.

  jclass eltClass = arrayClass->getComponentType();

  if (eltClass->isPrimitive())

    return eltClass->size();

  return sizeof (void *);

}

// These methods are used when the compiler fails to generate inline

// versions of the compare-and-swap primitives.

jboolean

sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,

                                           jint expect, jint update)

{

  jint *addr = (jint *)((char *)obj + offset);

  return compareAndSwap (addr, expect, update);

}

jboolean

sun::misc::Unsafe::compareAndSwapLong (jobject obj, jlong offset,

                                            jlong expect, jlong update)

{

  volatile jlong *addr = (jlong*)((char *) obj + offset);

  return compareAndSwap (addr, expect, update);

}

jboolean

sun::misc::Unsafe::compareAndSwapObject (jobject obj, jlong offset,

                                                jobject expect, jobject update)

{

  jobject *addr = (jobject*)((char *) obj + offset);

  return compareAndSwap (addr, expect, update);

}

void

sun::misc::Unsafe::putOrderedInt (jobject obj, jlong offset, jint value)

{

  volatile jint *addr = (jint *) ((char *) obj + offset);

  *addr = value;

}

void

sun::misc::Unsafe::putOrderedLong (jobject obj, jlong offset, jlong value)

{

  volatile jlong *addr = (jlong *) ((char *) obj + offset);

  spinlock lock;

  *addr = value;

}

void

sun::misc::Unsafe::putOrderedObject (jobject obj, jlong offset, jobject value)

{

  volatile jobject *addr = (jobject *) ((char *) obj + offset);

  *addr = value;

}

void

sun::misc::Unsafe::putIntVolatile (jobject obj, jlong offset, jint value)

{

  write_barrier ();

  volatile jint *addr = (jint *) ((char *) obj + offset);

  *addr = value;

}

void

sun::misc::Unsafe::putLongVolatile (jobject obj, jlong offset, jlong value)

{

  volatile jlong *addr = (jlong *) ((char *) obj + offset);

  spinlock lock;

  *addr = value;

}

void

sun::misc::Unsafe::putObjectVolatile (jobject obj, jlong offset, jobject value)

{

  write_barrier ();

  volatile jobject *addr = (jobject *) ((char *) obj + offset);

  *addr = value;

}

#if 0  // FIXME

void

sun::misc::Unsafe::putInt (jobject obj, jlong offset, jint value)

{

  jint *addr = (jint *) ((char *) obj + offset);

  *addr = value;

}

#endif

void

sun::misc::Unsafe::putLong (jobject obj, jlong offset, jlong value)

{

  jlong *addr = (jlong *) ((char *) obj + offset);

  spinlock lock;

  *addr = value;

}

void

sun::misc::Unsafe::putObject (jobject obj, jlong offset, jobject value)

{

  jobject *addr = (jobject *) ((char *) obj + offset);

  *addr = value;

}

jint

sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset)

{

  volatile jint *addr = (jint *) ((char *) obj + offset);

  jint result = *addr;

  read_barrier ();

  return result;

}

jobject

sun::misc::Unsafe::getObjectVolatile (jobject obj, jlong offset)

{

  volatile jobject *addr = (jobject *) ((char *) obj + offset);

  jobject result = *addr;

  read_barrier ();

  return result;

}

jlong

sun::misc::Unsafe::getLong (jobject obj, jlong offset)

{

  jlong *addr = (jlong *) ((char *) obj + offset);

  spinlock lock;

  return *addr;

}

jlong

sun::misc::Unsafe::getLongVolatile (jobject obj, jlong offset)

{

  volatile jlong *addr = (jlong *) ((char *) obj + offset);

  spinlock lock;

  return *addr;

}

void

sun::misc::Unsafe::unpark (::java::lang::Thread *thread)

{

  natThread *nt = (natThread *) thread->data;

  nt->park_helper.unpark ();

}

void

sun::misc::Unsafe::park (jboolean isAbsolute, jlong time)

{

  using namespace ::java::lang;

  Thread *thread = Thread::currentThread();

  natThread *nt = (natThread *) thread->data;

  nt->park_helper.park (isAbsolute, time);

}

猜你喜欢

转载自googi.iteye.com/blog/1583933
今日推荐