unSafe是什么?

53 篇文章 0 订阅
53 篇文章 0 订阅

unSafe

Java中unSafe类是什么?

  • java.util.concurrent包或者java.nio包中经常会看到sun.misc.Unsafe,类如其名,就是不建议使用(不安全、不轻便、不稳定)的、可以用于观察HotSpot JVM内部结构并且可以对其进行修改的一个“后门类”。(有时也可以用来做性能监控和开发工具)
  • Java官方不推荐使用,因为很难正确使用,如果使用错误会给JVM带来致命问题。
  • 但是很多Java基础类库,包括一些被广泛使用的高性能开发库都是基于Unsafe类开发的,比如:Netty、Hadoop、Kafaka等。
  • Unsafe类在提升Java运行效率增强Java语言底层操作能力方面作用很大。

如何使用?

  • Unsafe提供了一个私有的静态实例,并且通过检查classloader是否为null来避免java程序直接使用unsafe

    //Unsafe源码
    private static final Unsafe theUnsafe;
    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if(var0.getClassLoader() != null) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }
    
  • 反射获取Unsafe静态类

    /**
     * 获取Unsafe
     */
    Field f = null;
    Unsafe unsafe = null;
    try {
        f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        unsafe = (Unsafe) f.get(null);
    } catch (Exception e) {
        e.printStackTrace();
    }
    
  • 通过Unsafe分配使用堆外内存。C++中有malloc,realloc和free方法来操作内存。在Unsafe类中对应为:

    // 分配size字节大小的内存,返回起始地址偏移量
    public native long allocateMemory(long size);
    
    // 重新给address起始地址的内存分配长度为size字节大小的内存,返回新的内存起始地址偏移量
    public native long reallocateMemory(long address, long size);
    
    // 释放起始地址为address的内存
    public native void freeMemory(long address);
    
    // 分配内存方法还有重分配内存方法都是分配的堆外内存,返回的是一个long类型的地址偏移量。这个偏移量在你的Java程序中每块内存都是唯一的。
    
    堆外内存的好处?
      Java中创建对象都是堆内内存,由JVM管控的Java进程内存,遵循JVM的内存管理机制,通过垃圾回收机制统一管理堆内存。
      堆外内存,不受JVM管控,依赖于Unsafe提供的操作堆外内存的native方法。
      好处一:减少堆内内存垃圾回收的工作量,减少GC停顿时间。
      好处二:提升程序I/O操作性能,通常I/O操作过程中,涉及堆内内存到堆外内存的数据拷贝操作,对于频繁进行内存间数据拷贝且生命周期较短的暂存数据,建议存储到堆外内存。
    
    备注:实际地址=基址+偏移量
    
  • 线程挂起和恢复(通过park和unpack实现)

  • 内存屏障(是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作,避免指令重排序)

  • 实现对象copy(通过Unsafe的 public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7)方法来拷贝)

  • 一图胜千言:

    img

应用?

  • AtomicInteger的实现:

    public class AtomicInteger extends Number implements java.io.Serializable {
        private static final long serialVersionUID = 6214790243416807050L;
    
        // setup to use Unsafe.compareAndSwapInt for updates
        private static final Unsafe unsafe = Unsafe.getUnsafe();
      	// 静态字段valueOffset即为字段value的 内存偏移地址
        private static final long valueOffset;
    
        static {
            try {
                // 获取valueOffset
                valueOffset = unsafe.objectFieldOffset
                    (AtomicInteger.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
      	// volatile关键字修饰保证数据的可见性、有序性
        private volatile int value;
    		......
          
        public final boolean compareAndSet(int expect, int update) {
          	// 通过字段 valueOffset的值 可以定位到AtomicInteger对象中value的内存地址。可以根据CAS实现对value字段的原子操作。
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    }
    
    备注:
      1. CAS保障原子性吗?
      	 CAS是通过硬件命令保证了原子性,而i++没有,且硬件级别的原子性比i++这样高级语言的软件级别的运行速度要快得多。虽然CAS也包含了多个操作,但其运算是固定的(就是个比较),这样的锁定性能开销很小。
      2. CAS是自旋锁吗?
      	 CAS底层实际通过类似于 lock cmpxchgl 这种汇编的指令,通知CPU进行原子性的更新。这其实一个轻量的loc指令,可以让CPU保证原子性的操作,所以说CAS是自旋锁,是有道理的。
      3. CAS的自旋无限循环性能问题怎么优化?
      	 分段CAS(分段迁移),比如:LongAdder(当某一个线程如果对一个值更新是,可以看对这个值进行分段更新,每一段叫做一个Cell,在更新每一个Cell的时候,发现说出现了很难更新它的值,出现了多次 CAS失败了,自旋的时候,进行自动迁移段,它会去尝试更新别的分段Cell的值,这样的话就可以让一个线程不会盲目的CAS自旋等待一个更新分段cell的值)。简单理解,就是分段方式,你不行就试试别人,避免盲目死磕浪费时间。
      4. ABA问题?
      	 加一个类似于版本号的东西,比如邮戳int stamp之类的。记录更新的次数即可,比较的时候不光比较value也要比较邮戳。
    

Reference

  • https://blog.csdn.net/u011179993/article/details/79360930?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-1.opensearchhbase&spm=1001.2101.3001.4242.2(Java中的Unsafe类)
  • https://blog.csdn.net/F_Hello_World/article/details/103467669(Java中的Unsafe类)
  • https://www.cnblogs.com/candlia/p/11920170.html(堆外内存与堆内内存详解)
  • https://blog.csdn.net/xiaolinzi176/article/details/120753019(Atomic原子类与Unsafe魔法类详解)
  • https://blog.csdn.net/liangwenmail/article/details/80832580(CAS操作确保原子性)
  • https://baijiahao.baidu.com/s?id=1714420245669778311&wfr=spider&for=pc(JDK成长记17:Atomic类的原理—CAS+valotile)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Unsafe Deserialization,也称为反序列化漏洞,是一种安全漏洞,其发生在应用程序中的数据反序列化过程中。简单来说,当应用程序从外部数据源(例如网络或文件)接收序列化对象并尝试将其还原为原始对象时,如果未正确验证和过滤输入数据,攻击者可以将恶意代码注入反序列化流中,从而导致应用程序执行不受控制的操作。这可能会导致数据泄露、拒绝服务攻击、远程执行代码等安全问题。 ### 回答2: Unsafe Deserialization(不安全的反序列化)是指在编程语言中的反序列化过程中出现风险的情况。反序列化是将之前序列化为数据流的对象重新转换为对象的过程。在这个过程中,程序会将数据流转换为内存中的对象,在此过程中,可能存在潜在的安全问题。 反序列化的过程中,程序会根据数据流中的内容来创建对象,并将对象的状态恢复为序列化之前的状态。然而,如果攻击者能够在数据流中插入恶意代码,就可能导致安全漏洞。这种攻击方式被称为反序列化攻击。 反序列化攻击通常通过传递经过篡改的数据流来实现,攻击者可能利用漏洞来执行恶意代码,例如远程代码执行、拒绝服务攻击等。攻击者可以通过构造恶意的序列化数据来触发漏洞,从而获取未经授权的访问权限或者执行未经授权的操作。 为了防止Unsafe Deserialization攻击,开发人员可以采取一些预防措施。例如,使用白名单来限制反序列化的类、字段和方法,以防止执行恶意代码。另外,对于不可信的数据流,可以使用加密、签名或者其他验证机制来确保数据的完整性和安全性。 总之,Unsafe Deserialization是指在反序列化过程中存在潜在的安全隐患,攻击者可能通过构造恶意的序列化数据来执行未经授权的操作。开发人员应该采取预防措施来保护应用程序免受此类攻击。 ### 回答3: Unsafe Deserialization(不安全的反序列化)是指在程序中反序列化数据时存在的安全漏洞。反序列化是将存储在文件或网络中的序列化数据转换为可操作的对象的过程。然而,如果反序列化过程没有适当的安全措施,攻击者可能利用这个漏洞来执行恶意代码或实现其他恶意行为。 Unsafe Deserialization的安全问题主要出现在未对反序列化数据进行充分验证和过滤的情况下。攻击者可以通过构造精心设计的恶意数据,改变其原始目的,以实现各种攻击目标。例如,攻击者可能通过篡改序列化数据来执行远程代码执行(Remote Code Execution)攻击,获取系统权限,并在目标系统上执行任意的恶意操作,如数据盗取、篡改或删除。 为了防止Unsafe Deserialization漏洞,开发人员可以采取以下措施: 1. 使用安全的序列化库:选择可信赖的序列化库,例如JSON,它提供了很多安全特性,并且有很好的社区支持。 2. 输入验证和过滤:对反序列化的输入数据进行严格的验证和过滤,确保只接受符合预期数据结构的数据。 3. 加强访问控制:仅允许受信任的类进行反序列化操作,并禁止反序列化敏感数据。 4. 使用白名单:定义合法的序列化类和对象,将所有其他类和对象视为不受信任,从而限制攻击者能够注入恶意代码的可能性。 5. 更新和修补:及时应用安全补丁和更新,以修复已知的安全漏洞。 总之,Unsafe Deserialization是一种可能导致严重安全问题的漏洞,需要开发人员在编写反序列化代码时采取适当的安全措施来防范和修复。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值