注:本文出自"美团技术团队"微信公众号

Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使Java语言拥有了类似C语言指针一样操作内存空间的能力,这无疑也增加了程序发生相关指针问题的风险。在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重。

本文对sun.misc.Unsafe公共API功能及相关应用场景进行介绍。

基本介绍:

如下Unsafe源码所示,Unsafe类为一单例实现,提供静态方法getUnsafe()获取Unsafe实例,当且仅当调用getUnsafe方法的类为引导类加载器所加载时才合法,否则抛出SecurityException异常。

pubic class Unsafe{//单例对象private static final Unsafe theUnsafe;private Unsafe(){}@CallerSensitivepublic static Unsafe getUnsafe() {Class var0 = Reflection.getCallerClass();//仅在引导类加载器BootstrapClassLoader加载时才合法if (!VM.isSystemDomainLoader(var0.getClassLoader())) {throw new SecurityException("Unsafe");} else {return theUnsafe;}}
}

那如若想使用这个类,该如何获取其实例?有如下两个可行方案。

其一,从getUnsafe方法的使用限制条件出发,通过Java命令行命令-Xbootclasspath/a把调用Unsafe相关方法的类A所在jar包路径追加到默认的bootstrap路径中,使得A被引导类加载器加载,从而通过Unsafe.getUnsafe方法安全的获取Unsafe实例。

java -Xbootclasspath/a:${path} // 其中path为调用Unsafe相关方法的类所在jar包路径 

其二,通过反射获取单例对象theUnsafe。

private static Unsafe reflectionGetUnsafe(){try{Field field = Unsafe.class.getDeclaredField("theUnsafe");field.setAccessible(true);return (Unsafe) field.get(null);}catch(Exception e){logger.error(e.getMesage(),e);return null;}
}

功能介绍:

如上图所示,Unsafe提供的API大致可分为内存操作、CAS、Class相关、对象操作、线程调度、系统信息获取、内存屏障、数组操作等几类,下面将对其相关方法和应用场景进行详细介绍。

内存操作:

这部分主要包含堆外内存的分配、拷贝、释放、给定地址值操作等方法。

//分配内存, 相当于C++的malloc函数
public native long allocateMemory(long bytes);
//扩充内存
public native long reallocateMemory(long address, long bytes);
//释放内存
public native void freeMemory(long address);
//在给定的内存块中设置值
public native void setMemory(Object o, long offset, long bytes, byte value);
//内存拷贝
public native void copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
//获取给定地址值,忽略修饰限定符的访问限制。与此类似操作还有: getInt,getDouble,getLong,getChar等
public native Object getObject(Object o, long offset);
//为给定地址设置值,忽略修饰限定符的访问限制,与此类似操作还有: putInt,putDouble,putLong,putChar等
public native void putObject(Object o, long offset, Object x);
//获取给定地址的byte类型的值(当且仅当该内存地址为allocateMemory分配时,此方法结果为确定的)
public native byte getByte(long address);
//为给定地址设置byte类型的值(当且仅当该内存地址为allocateMemory分配时,此方法结果才是确定的)
public native void putByte(long address, byte x);

通常,我们在Java中创建的对象都处于堆内内存(heap)中,堆内内存是由JVM所管控的Java进程内存,并且它们遵循JVM的内存管理机制,JVM会采用垃圾回收机制统一管理堆内内存。与之相对的是堆外内存,存在于JVM管控之外的内存区域,Java中对堆外内存的操作,依赖于Unsafe提供的操作堆外内存的native方法。

使用堆外内存的原因:

  • 对垃圾回收停顿的改善。由于堆外内存是直接受操作系统管理而不是JVM,所以当我们使用堆外内存时,即可保持较小的堆内内存规模。从而在GC时减少回收停顿对于应用的影响。
  • 提升程序I/O操作的性能。通常在I/O通信过程中,会存在堆内内存到堆外内存的数据拷贝操作,对于需要频繁进行内存间数据拷贝且生命周期较短的暂存数据,都建议存储到堆外内存。

典型应用:

DirectByteBuffer是Java用于实现堆外内存的一个重要类,通常用在通信过程中做缓冲池,如在Netty、MINA等NIO框架中应用广泛。DirectByteBuffer对于堆外内存的创建、使用、销毁等逻辑均由Unsafe提供的堆外内存API来实现。

CAS相关:

线程调度:

Class相关:

对象操作:

数组相关:

内存屏障:

系统相关:

转载于:https://www.cnblogs.com/i-hard-working/p/10390052.html

Java中的指针---Unsafe应用解析相关推荐

  1. java unsafe获取指针_【实战Java高并发程序设计 1】Java中的指针:Unsafe类

    是<实战Java高并发程序设计>第4章的几点. 如果你对技术有着不折不挠的追求,应该还会特别在意incrementAndGet() 方法中compareAndSet()的实现.现在,就让我 ...

  2. java 指针_java多线程学习二十二:::java中的指针

    在上面那个图,我们看到一个特殊的变量unsafe,它的包名是 sun.misc.Unsafe;从名字看,这个类应该是封装一些不安全的操作,为什么不安全?对c语言理解的朋友就知道了,指针是不安全的,在j ...

  3. java中构造方法和方法全面解析

    java中构造方法和方法全面解析 我相信大多说人都对构造方法.方法不陌生,而且很了解,但我也相信有很多像我这样的没有一个很好很清晰很全面的认识,今天就把它整理如下,希望能给大家带来点方便与帮助,也希望 ...

  4. java int 指针_如何在Java中使用指针?

    小编典典 Java中的所有对象都是引用,你可以像使用指针一样使用它们. abstract class Animal {... } class Lion extends Animal {... } cl ...

  5. Java中4大基本加密算法解析

    Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一, 大家可以查看RFC2045- RFC2049, 上面有MIME的详细规范. 简单的java加密算法有: BASE64 严格地说, ...

  6. c语言野指针应用,C语言中野指针的深入解析

    C语言中野指针的深入解析 C语言中野指针这一块是C语言的难点,下面小编为大家带来了C语言中野指针的深入解析,欢迎大家阅读! "野指针"的成因主要有两种: (1)指针变量没有被初始化 ...

  7. Java魔法类:Unsafe应用解析

    Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别.不安全操作的方法,如直接访问系统内存资源.自主管理内存资源等,这些方法在提升Java运行效率.增强Java语言底层资源操作能 ...

  8. 【基本功】Java魔法类:Unsafe应用解析

    总第334篇 2019年 第12篇 大家好,我是程序员鼓励师美美- <基本功>专栏又上新了:Java中的Unsafe类在提升运行效率.增强底层资源操作能力方面有很大的用处.但如果在开发过程 ...

  9. this指针 java_彻底理解Java中this指针

    每次看到Java中的this指针,总摸不着头绪.在网上看了很多人的讲解,还是不知道this指针到底是什么东西,今天的的这篇日志可以让你看清this到底是谁.(内容摘自:http://www.mathc ...

  10. Java中的注解(Annotation)处理器解析

    Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...

最新文章

  1. 用python画烟花-python实现烟花小程序
  2. FluentEmail - 适用于 .NET 和 .NET Core 的邮件发送库
  3. linux文件属性之用户和组基础知识
  4. spring之依赖注入
  5. datepick二格式 化时间_同样是持久化,竟然有这么大的差别
  6. c 连接mysql自动断开_ESQL/C连接和断开数据库(INFORMIX) | 学步园
  7. 【转】卡巴斯基2011导入key专用工具+卡巴斯基提取key工具(激活码转换key)
  8. PDM系统服务器管理,PDM产品数据管理系统
  9. python列表所有元素平均值_python—组合数据类型
  10. 武田呈报mobocertinib的最新结果,进一步证实EGFR外显子20插入+ mNSCLC患者的临床收益
  11. 葫芦娃游戏维护服务器怎么办,葫芦娃一直进不去 无法进入游戏解决方法
  12. 古籍研究社系列第6部《迟来的翅膀》读后感……吗?
  13. hrbust 1313 火影忍者之~静音【优先队列STL+模拟】
  14. 卡卡又一次双手举天,巴西涉险过关,克罗地亚虽败尤荣.
  15. 阿狸表情图采集代码示例
  16. 高维非空间数据可视化
  17. Python学习日记-day1基础篇 字符 输出 注释
  18. 浏览器打不开服务器网页,浏览器打不开某几个网页,这样来解决
  19. 应用“真心话大冒险”已更新到marketplace中
  20. [WEB攻防] i春秋- “百度杯”CTF比赛 十二月场-YeserCMS cmseasy CmsEasy_5.6_20151009 无限制报错注入 复现过程

热门文章

  1. 《Flash ActionScript 3.0 动画高级教程》
  2. R语言机器学习中数据可视化的杀手锏
  3. 查看Oracle数据库的用户名和密码
  4. C#中Dictionary的用法及用途(转)
  5. #pragma pack与sizeof union
  6. extjs-mvc结构实践(二):基本页面
  7. webpack如何全局引入jquery和echarts?
  8. angular的组件通信
  9. 大数据时代的可扩展性数据库集群技术
  10. Web服务及http协议_学习笔记