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来计算下字段的偏移地址,一则验证 ...
随机推荐
- 定期删除elasticsearch 的index 索引
#!/bin/bashfind /data/elasticsearch/data/pro-kz-log/nodes/0/indices/ -type d -mtime +7 | awk -F" ...
- C++ 读写MySQL经典 (转载)
from: http://blog.csdn.net/jemlee2002/article/details/1523164 看过很多C或是C++操作MySQL数据库的文章,大部分太吃力了,甚至有一 ...
- 在TypeScript中扩展JavaScript基础对象的功能
最近工作中用到,记录一下:假设我们需要一个功能,把一个数字比如10000输出为下面的字符串格式“10,000”,一般是写一个方法,那么我希望更方便一点,直接向Number类型添加一个格式化方法,比如叫 ...
- FFmpeg(4)-使用avformat_find_stream_info()来探测获取封装格式的上下文信息
/** * Read packets of a media file to get stream information. This * is useful for file formats with ...
- android---笔记 AppContext extends Application
package com.fuda; import org.apache.http.client.CookieStore; import com.fuda.model.StudentInfoModel; ...
- Backpropagation In Convolutional Neural Networks
http://www.jefkine.com/general/2016/09/05/backpropagation-in-convolutional-neural-networks/ http://w ...
- Python 3.6 安装pip
1.首先python3.4以后,pip内嵌,不过使用方法是: python -m pip install django 2.如果你觉得上面的指令太长,想用旧方法使用pip,那用以下指令安装pip即可 ...
- 银联在线支付B2C UnionPay.NET
新春即将来临,首先给大家拜个早年,祝攻城狮们新年快乐.万事如意.合家欢乐.团团圆圆.幸福健康.来年更能大展宏图 实现各自的梦想! 同时预祝各大科技公司大佬们事业蒸蒸日上.公司转型突破创新.冲出突围带领 ...
- (原创)c++11改进我们的模式之改进表驱动模式
所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值.表驱动是将一些通过较为复杂逻辑语句来得到数据信息的方式,通过查询表的方式来实现,将数据信息存放在表里.对于消除 ...
- 【Fiddler】Fiddler抓包
简述 在调试H5页面.APP的网络请求时,常用Fiddler进行抓包,查看网络报文是否如我们设想.当然,Fiddler也可对我们电脑端发出HTTP请求进行抓包. Fiddler是以代理的形式运行的,即 ...