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类的更多相关文章

  1. Java sun.misc.Unsafe类的学习笔记

    Java未开源的Unsafe类 Unsafe类可以为我们提供高效并且线程安全方式操作变量,直接和内存数据打交道. 获取Unsafe实体的方法 private static Unsafe getUnsa ...

  2. JDK 1.8 sun.misc.Unsafe类CAS底层实现

    在java.util.concurrent包下面的很多类为了追求性能都采用了sun.misc.Unsafe类中的CAS操作,从而避免使用synchronized等加锁方式带来性能上的不足. 在sun. ...

  3. Java的sun.misc.Unsafe类

    阅读目录 前言 Unsafe类的作用 获取Unsafe对象 Unsafe类中的API 前言 以下sun.misc.Unsafe源码和demo基于jdk1.7: 最近在看J.U.C里的源码,很多都用到了 ...

  4. 并发编程之sun.misc.Unsafe类

    1.Unsafe知识点整理 2.代码: package com.javabasic.unsafe; import java.lang.reflect.Field; import sun.misc.Un ...

  5. sun.misc.unsafe类的使用

    http://blog.csdn.net/fenglibing/article/details/17138079

  6. eclipse无法访问sun.misc.Unsafe类的解决办法

    参考:https://www.cnblogs.com/duanxz/p/6090442.html

  7. java.util.concurrent各组件分析 一 sun.misc.Unsafe

    java.util.concurrent各组件分析 一 sun.misc.Unsafe 说到concurrent包也叫并发包,该包下主要是线程操作,方便的进行并发编程,提到并发那么锁自然是不可缺少的, ...

  8. sun.misc.Unsafe 详解

    原文地址 译者:许巧辉 校对:梁海舰 Java是一门安全的编程语言,防止程序员犯很多愚蠢的错误,它们大部分是基于内存管理的.但是,有一种方式可以有意的执行一些不安全.容易犯错的操作,那就是使用Unsa ...

  9. java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值

    在上一篇文章中.我们列出了计算java对象大小的几个结论以及jol工具的使用,jol工具的源代码有兴趣的能够去看下.如今我们利用JDK中的sun.misc.Unsafe来计算下字段的偏移地址,一则验证 ...

随机推荐

  1. xctool + oclint 安装使用

    使用brew 安装Xctool 先跟新brew : sudo  brew update brew install xctool --HEAD OK. 使用请参照 文档 如: xctool -works ...

  2. MySQL与Oracle的区别之我见

    1. 大的方面(宏观) Oracle为商用数据库,行业中占据相当的地位:市场占比2012年为40%.开发.管理资源相当丰富,有自己的metalink,我也曾用过,有什么问题,都能在那里得到较快速度的解 ...

  3. Android API 指南

    原文链接:http://android.eoe.cn/topic/android_sdk Android API 指南 - Android API Guides 应用的组成部分 - Applicati ...

  4. Filberder教程

    http://www.cnblogs.com/TankXiao/archive/2012/02/06/2337728.html

  5. git clean 小结

    删除 一些 没有 Git add 的 文件: git clean 参数 -n 显示 将要 删除的 文件 和  目录 -f 删除 文件,-df 删除 文件 和 目录 git clean -n git c ...

  6. 正确使用 Volatile 变量

    Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...

  7. NET Core 1.1 版本项目和2.0环境下的项目开发注意事项

    在NET Core 1.1开发下的项目最好不要随便把工具更新升级到2.0,这样最容易导致之前的.NETCore直接被升级不兼容早前版本 会引起项目无法启动在运行调试IIS express 时候直接一闪 ...

  8. 每日英语:Nelson Mandela Dies at 95

    Nelson Mandela, who rose from militant antiapartheid activist to become the unifying president of a ...

  9. 【嵌入式】S3C2410平台移植linux 2.6.14内核

    小续 第一次接触内核的东西,有点小激动啊 激动归激动,这实验还是要继续做下去,书上三两句话就带过去的,剩下的就留给我们了,着实考验动手能力啊 当编译过内核之后,发现这个过程也不复杂嘛(复杂的是内核的配 ...

  10. 大量的源文件添加到Android.mk的问题

    LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := game_shared LOCAL_MODULE_FILENAME ...