Java sun.misc.unsafe类
Java是一个安全的开发工具,它阻止开发人员犯很多低级的错误,而大部份的错误都是基于内存管理方面的。如果你想搞破坏,可以使用Unsafe这个类。这个类是属于sun.*API中的类,并且它不是J2SE中真正的一部份,因此你可能找不到任何的官方文档,更可悲的是,它也没有比较好的代码文档。
Unsafe的功能:
1、实例化sun.misc.Unsafe
如果你尝试创建Unsafe类的实例,基于以下两种原因是不被允许的。
1)、Unsafe类的构造函数是私有的;
2)、虽然它有静态的getUnsafe()方法,但是如果你尝试调用Unsafe.getUnsafe(),会得到一个SecutiryException(因为要求调用unsafe的类为bootstrap类加载器所加载)。这个类只有被JDK信任的类实例化。但是这总会是有变通的解决办法的,一个简单的方式就是使用反射进行实例化:
Field f = Unsafe.class.getDeclaredField("theUnsafe"); //Internal reference
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
注:IDE如Eclipse会对这样的使用报错,不过不用担心,直接运行代码就行。
(还有一种解决方法,就是将Eclipse中这种限制由错误,修改为警告,具体操作为将Windows->Preference...->Java->Compiler->Errors/Warnings中的"DeprecatedandrestrictedAPI",级别由Error修改为Warning就可以了)
现在进入主题,使用这个对象我们可以做如下“有趣的”事情。
2、使用sun.misc.Unsafe
2.1、突破限制创建实例
通过allocateInstance()方法,你可以创建一个类的实例,但是却不需要调用它的构造函数、初使化代码、各种JVM安全检查以及其它的一些底层的东西。即使构造函数是私有,我们也可以通过这个方法创建它的实例。
public class UnsafeDemo {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
Field f = Unsafe.class.getDeclaredField("theUnsafe"); // Internal reference
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null); // This creates an instance of player class without any initialization
Player p = (Player) unsafe.allocateInstance(Player.class);
System.out.println(p.getAge()); // Print 0 p.setAge(45); // Let's now set age 45 to un-initialized object
System.out.println(p.getAge()); // Print 45
}
} class Player {
private int age = 12; private Player() {
this.age = 50;
} public int getAge() {
return this.age;
} public void setAge(int age) {
this.age = age;
}
}
2.2、直接申请、操作物理内存(Java中Bits.byteOrder()就用了此法)
Field f = Unsafe.class.getDeclaredField("theUnsafe"); // Internal reference
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
long a = unsafe.allocateMemory(8);
System.out.printf("0x%2X 0x%2X\n", a, (a + 1));
try {
unsafe.putLong(a, 0x0102030405060708L);
byte b = unsafe.getByte(a);
System.out.println(b); } finally {
unsafe.freeMemory(a);
}
2.3、常量Integer.MAX_VALUE是JAVA中数组长度的最大值,如果想创建一个非常大的数组(虽然在通常的应用中不可能会用上,且可能会导致JVM挂掉),可以通过对内存进行直接分配实现。
// 虽然可分批的元素个数(Long.MAX_VALUE)比Java本身的(Integer.MAX_VALUE)大,但可能会导致JVM挂掉。
class SuperArray {
Unsafe unsafe;
private long address;// 字节数组起始地址
private byte byteLenOfElementType;// 一个元素所占字节数
private long size;// 元素个数 /**
* 初始化一个大数组
*
* @param elemet_num
* 元素的个数
* @param bytes_of_element_type
* 每个元素占用的字节数
*/
public SuperArray(Unsafe unsafe, long elemet_num, byte bytes_of_element_type) {
this.unsafe = unsafe;
this.byteLenOfElementType = bytes_of_element_type;
this.size = elemet_num; // 得到分配内存的起始地址
this.address = unsafe.allocateMemory(size * byteLenOfElementType);
} /**
* 给数组某个元素赋值
*
* @param index
* 元素下标
* @param value
* 元素值
*/
public void set(long index, byte[] value) {
long startAddr = address + index * byteLenOfElementType;
for (byte i = 0; i < byteLenOfElementType; i++) {
unsafe.putByte(startAddr + i, value[i]);
}
} public byte[] get(long idx) {
byte[] res = new byte[byteLenOfElementType];
long startAddr = address + idx * byteLenOfElementType;
for (byte i = 0; i < byteLenOfElementType; i++) {
res[i] = unsafe.getByte(startAddr + i);
}
return res;
} public long size() {
return size;
}
}
3、参考资料
1、Java Magic. Part 4: sun.misc.Unsafe
2、http://blog.csdn.net/fenglibing/article/details/17138079
3、https://blog.csdn.net/javazejian/article/details/72772470(更多Unsafe相关)
4、https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html (美团技术团队文章)
Java sun.misc.unsafe类的更多相关文章
- Java sun.misc.Unsafe类的学习笔记
Java未开源的Unsafe类 Unsafe类可以为我们提供高效并且线程安全方式操作变量,直接和内存数据打交道. 获取Unsafe实体的方法 private static Unsafe getUnsa ...
- JDK 1.8 sun.misc.Unsafe类CAS底层实现
在java.util.concurrent包下面的很多类为了追求性能都采用了sun.misc.Unsafe类中的CAS操作,从而避免使用synchronized等加锁方式带来性能上的不足. 在sun. ...
- Java的sun.misc.Unsafe类
阅读目录 前言 Unsafe类的作用 获取Unsafe对象 Unsafe类中的API 前言 以下sun.misc.Unsafe源码和demo基于jdk1.7: 最近在看J.U.C里的源码,很多都用到了 ...
- 并发编程之sun.misc.Unsafe类
1.Unsafe知识点整理 2.代码: package com.javabasic.unsafe; import java.lang.reflect.Field; import sun.misc.Un ...
- sun.misc.unsafe类的使用
http://blog.csdn.net/fenglibing/article/details/17138079
- eclipse无法访问sun.misc.Unsafe类的解决办法
参考:https://www.cnblogs.com/duanxz/p/6090442.html
- java.util.concurrent各组件分析 一 sun.misc.Unsafe
java.util.concurrent各组件分析 一 sun.misc.Unsafe 说到concurrent包也叫并发包,该包下主要是线程操作,方便的进行并发编程,提到并发那么锁自然是不可缺少的, ...
- sun.misc.Unsafe 详解
原文地址 译者:许巧辉 校对:梁海舰 Java是一门安全的编程语言,防止程序员犯很多愚蠢的错误,它们大部分是基于内存管理的.但是,有一种方式可以有意的执行一些不安全.容易犯错的操作,那就是使用Unsa ...
- java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值
在上一篇文章中.我们列出了计算java对象大小的几个结论以及jol工具的使用,jol工具的源代码有兴趣的能够去看下.如今我们利用JDK中的sun.misc.Unsafe来计算下字段的偏移地址,一则验证 ...
随机推荐
- xctool + oclint 安装使用
使用brew 安装Xctool 先跟新brew : sudo brew update brew install xctool --HEAD OK. 使用请参照 文档 如: xctool -works ...
- MySQL与Oracle的区别之我见
1. 大的方面(宏观) Oracle为商用数据库,行业中占据相当的地位:市场占比2012年为40%.开发.管理资源相当丰富,有自己的metalink,我也曾用过,有什么问题,都能在那里得到较快速度的解 ...
- Android API 指南
原文链接:http://android.eoe.cn/topic/android_sdk Android API 指南 - Android API Guides 应用的组成部分 - Applicati ...
- Filberder教程
http://www.cnblogs.com/TankXiao/archive/2012/02/06/2337728.html
- git clean 小结
删除 一些 没有 Git add 的 文件: git clean 参数 -n 显示 将要 删除的 文件 和 目录 -f 删除 文件,-df 删除 文件 和 目录 git clean -n git c ...
- 正确使用 Volatile 变量
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...
- NET Core 1.1 版本项目和2.0环境下的项目开发注意事项
在NET Core 1.1开发下的项目最好不要随便把工具更新升级到2.0,这样最容易导致之前的.NETCore直接被升级不兼容早前版本 会引起项目无法启动在运行调试IIS express 时候直接一闪 ...
- 每日英语:Nelson Mandela Dies at 95
Nelson Mandela, who rose from militant antiapartheid activist to become the unifying president of a ...
- 【嵌入式】S3C2410平台移植linux 2.6.14内核
小续 第一次接触内核的东西,有点小激动啊 激动归激动,这实验还是要继续做下去,书上三两句话就带过去的,剩下的就留给我们了,着实考验动手能力啊 当编译过内核之后,发现这个过程也不复杂嘛(复杂的是内核的配 ...
- 大量的源文件添加到Android.mk的问题
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := game_shared LOCAL_MODULE_FILENAME ...