sun.misc.Unsafe

转载 2013年12月04日 00:58:34

Java不能直接访问操作系统底层,而是通过本地方法来访问,Unsafe提供了硬件级别的原子操作,提供了以下功能:

分配、释放内存

操作内存主要依靠下面三个方法:

  1. allocateMemory:分配内存;
  2. reallocateMemory:扩充内存;
  3. freeMemory:释放内存;

操作对象的字段

Java对象中字段的定位可以通过staticFieldOffset实现,而读取具体便宜位置的字段的值可以使用getLong(根据不同类型选择不同的函数)来完成,可以使用putLong(根据不同的类型选择不同的函数)来设置值,可以使用arrayBaseOffset(获取数组第一个元素的偏移地址)和arrayIndexScale(获取数组中元素增量的地址)来访问数组中的元素。

CAS操作

CAS操作(会在java.util.concurrent中大量地使用)包括三个操作数:

  1. 内存位置;
  2. 预期原值;
  3. 新值;

如果内存位置的值与预期的值相等,那么处理器会将该位置的值设置为新值,否则,处理器不做任何处理。int类型的CAS实现如下:

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;
}

这段代码看起来根本无法保证操作的原子性,而其中的关键就在于spinlock lock这段看似没有用的代码,这时会调用构造函数,其中不停检查lock的值是否为0,如果不是0则线程让步等到线程下次执行时再次检查;否则,将lock设置为1。在离开函数的时候会调用其析构函数,将lock的值再次设置为0。spinlock的代码如下:

class spinlock
{
    static volatile obj_addr_t lock;
public:
    spinlock ()
    {
        while (!compare_and_swap(&lock, 0, 1))
            _Jv_ThreadYield();
    }
    ~spinlock ()
    {
        release_set(&lock, 0);
    }
};

而且,不管是在多核还是在单核的情况下,总是需要一些特殊的手段才能保证CAS操作成功吧,比如锁总线,compare_and_swap的实现如下:

inline static bool compare_and_swap(volatile obj_addr_t *addr, obj_addr_t old, obj_addr_t new_val)
{
    char result;
    #ifdef __x86_64__ __asm__ __volatile__("lock; cmpxchgq %2, %0; setz %1"
        : "=m"(*(addr)), "=q"(result)
        : "r" (new_val), "a"(old), "m"(*addr)
        : "memory");
    #else
        __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"
        : "=m"(*addr), "=q"(result)
        : "r" (new_val), "a"(old), "m"(*addr)
        : "memory");
    #endif
    return (bool) result;
}

挂起和恢复

使用park方法将一个线程挂起,知道超时或者中断等条件出现,实现如下:

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);
}

 使用unpark来终止一个挂起的线程,使其恢复正常,实现如下:

sun::misc::Unsafe::unpark (::java::lang::Thread *thread)
{
    natThread *nt = (natThread *) thread->data;
    nt->park_helper.unpark ();
}

----- -- -

END

sun.misc.Unsafe源码

  • 2017年12月04日 22:42
  • 9KB
  • 下载

sun.misc.Unsafe的各种神技

sun.misc.Unsafe源码解析,各种有趣的玩法,实例化私有构造类 创建超级数组, park阻塞 unpark恢复阻塞...

【JAVA笔记——道】JAVA内存操作 sun.misc.Unsafe类

TIP:这是一个很危险的类,不熟悉情况下别用于生产环境我们知道JAVA作为高级语言的重要创新一点就是在于JVM的内存管理功能,这完全区别于C语言开发过程中需要对变量的内存分配小心控制,JVM很大程度解...

源码剖析之sun.misc.Unsafe

转载于:http://zeige.iteye.com/blog/1182571 首先介绍一下什么是Compare And Swap(CAS)?简单的说就是比较并交换。 CAS 操作包含三个...
  • zgmzyr
  • zgmzyr
  • 2013年05月08日 21:52
  • 7822

sun.misc.Unsafe实例介绍

java.util.concurrent 包下很多类的实现用到了基于硬件的CAS算法, 不再使用synchronized关键来进行并发控制,查看相关的源码后会发现最后都指向了一个类 ,这就是SUN未开...

sun.misc.Unsafe的后启示录

come from:http://www.infoq.com/cn/articles/A-Post-Apocalyptic-sun.misc.Unsafe-WorldJava语言和JVM平台已经度过了...

sun.misc.Unsafe源码解析

sun.misc.Unsafe源码解析 CAS原子操作

java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值

我们利用JDK中的sun.misc.Unsafe来计算下字段的偏移地址,一则验证下之前文章中的结论,再则跟jol输出结果对比下。通过上面的几段代码,我们可以成功获取类中各个字段的偏移地址,这跟jol工...

聊聊序列化(二)使用sun.misc.Unsafe绕过new机制来创建Java对象

在序列化的问题域里面有一个常见的问题,就是反序列化时用何种方式来创建Java对象,因为反序列化的目的是把一段二进制流转化成一个对象。 在Java里面创建对象有几种方式: 1. 显式地调用new语句...
  • ITer_ZC
  • ITer_ZC
  • 2014年11月05日 11:59
  • 3163

关于sun.misc.Unsafe类的使用(待完善)

http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
  • wz408
  • wz408
  • 2014年12月17日 20:31
  • 848
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:sun.misc.Unsafe
举报原因:
原因补充:

(最多只允许输入30个字)