UnSafe类的方法

本文探讨了Java中的Unsafe类,它提供了底层操作功能,如内存管理和并发控制。然而,不当使用可能导致安全问题。作者强调了使用Unsafe类需谨慎,并提到了它的主要作用和CAS方法,以及本地方法的特性。
摘要由CSDN通过智能技术生成

Unsafe类是Java中的一个特殊类,位于sun.misc包下。它提供了一系列方法,用于执行低级别的、不安全的操作,如直接访问系统内存资源和自主管理内存资源等。这些方法在提升Java程序的运行效率和增强对底层资源的操作能力方面起到了重要作用。

然而,Unsafe类的使用也带来了一定的风险。由于它赋予了Java类似C语言指针操作内存空间的能力,过度或不正确地使用Unsafe类可能导致程序出现指针相关的问题,从而增加了出错的概率。这使得原本安全的Java语言变得不再"安全"。因此,在使用Unsafe类时需要格外谨慎。

需要注意的是,尽管Unsafe类的方法都是public的,但并不意味着可以随意使用它们。JDK API文档也没有提供关于这个类方法的解释。对于Unsafe类的使用是受到限制的,只有经过授权的代码才能获得该类的实例。当然,JDK库中的类是可以随意使用Unsafe类的。

Unsafe 类的主要作用大致为:

  • 内存管理:Unsafe 类可以用于分配和释放内存,允许开发者直接操作内存资源。
  • 非常规的对象实例化:Unsafe 允许不通过构造函数创建对象实例。
  • 操作类、对象、变量:可以对类、对象和变量进行底层操作,如通过内存偏移地址访问对象的属性等。
  • 自定义超大数组操作:支持超过普通数组界限的数组操作。
  • 多线程同步:提供锁机制、CAS(Compare And Swap)操作等多线程同步功能。
  • 线程挂起与恢复:能够挂起和恢复线程的执行。
  • 内存屏障:用于控制指令重排,保证内存操作的顺序性。

以下是几个cas方法:

public final int getAndAddInt(Object paramObject, long paramLong, int paramInt)
  {
    int i;
    do
      i = getIntVolatile(paramObject, paramLong);
    while (!compareAndSwapInt(paramObject, paramLong, i, i + paramInt));
    return i;
  }

  public final long getAndAddLong(Object paramObject, long paramLong1, long paramLong2)
  {
    long l;
    do
      l = getLongVolatile(paramObject, paramLong1);
    while (!compareAndSwapLong(paramObject, paramLong1, l, l + paramLong2));
    return l;
  }
   public final Object getAndSetObject(Object paramObject1, long paramLong, Object paramObject2)
  {
    Object localObject;
    do
      localObject = getObjectVolatile(paramObject1, paramLong);
    while (!compareAndSwapObject(paramObject1, paramLong, localObject, paramObject2));
    return localObject;
  }

从源码中发现,内部使用自旋的方式进行CAS更新(while循环进行CAS更新,如果更新失败,则循环再次重试)。
Unsafe提供的3种CAS方法:

  1. compareAndSwapObject
  2. compareAndSwapInt
  3. compareAndSwapLong

以下是以序列图表示compareAndSwapInt方法如何在并发环境中被调用:
在这里插入图片描述

Unsafe的cas底层

Unsafe的compareAndSwap*方法来实现CAS操作,它是一个本地方法,实现位于unsafe.cpp中。

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");
  oop p = JNIHandles::resolve(obj);
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

Unsafe其它功能

Unsafe 提供了硬件级别的操作,比如说获取某个属性在内存中的位置,比如说修改对象的字段值,即使它是私有的。不过 Java 本身就是为了屏蔽底层的差异,对于一般的开发而言也很少会有这样的需求。
获取paramField 的内存地址偏移量:

public native long staticFieldOffset(Field paramField);

分配内存:

public native long allocateMemory(long paramLong);

扩充内存:

public native long reallocateMemory(long paramLong1, long paramLong2);

释放内存:

public native void freeMemory(long paramLong);

总结

由于 Unsafe 类提供了类似 C 语言指针的操作能力,过度或不正确使用可能会增加程序出错的风险,导致 Java 语言变得不再“安全”。因此,在使用 Unsafe 类时必须非常谨慎,并确保充分理解其工作原理和潜在风险。

值得注意的是,Unsafe 类的实现依赖于本地方法(Native Method),这些本地方法是用其他编程语言编写的,并且与操作系统底层紧密相关。

  • 16
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

π克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值