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. 《Java Concurrency》读书笔记,构建线程安全应用程序

    1. 什么是线程安全性 调用一个函数(假设该函数是正确的)操作某对象常常会使该对象暂时陷入不可用的状态(通常称为不稳定状态),等到操作完全结束,该对象才会重新回到完全可用的状态.如果其他线程企图访问一 ...

  2. Zynq开发之HLS

    Zynq开发之HLS 由 FPGA菜鸟 于 星期三, 06/28/2017 - 11:53 发表 HLS简介 HLS(High Level Synthesis)即高层次综合,不同于以往的FPGA逻辑开 ...

  3. 菜鸟学Java(十八)——异常

    每个学编程的人在编程的过程中都会遇到各种异常.那么当我们遇到异常的时候该怎么处理呢?针对不同的异常我们又该采取什么具体的处理方式呢?这些问题在我开始学编程的很长一段时间里我都不太清楚,还好随着不断的学 ...

  4. DIOCP开源项目-DIOCP3的ECHO测试<贴图>

    星期六开了测试台测试机子.星期天休息,今天早上来接两个图 开了2个客户端,一个qsl的echo client,一个是楠楠的dbiocp回调客户端.建立13240个连接 今天来后,机子很卡,后来发现是楠 ...

  5. 如何使用IDEA开发工具中右键中的Git图形化工具

    首先,你的项目一定是git服务器上面down下来的,下面来演示如何使用IntelliJ IDEA 开发中在鼠标右键中提供的一个非常方便的图形化Git管理工具: 这里使用的IDEA开发工具的版本是 In ...

  6. 测试redis集群的两种方式:分片和哨兵

    import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; i ...

  7. 如何使cmd窗口正确显示utf-8编码的文字

    http://blog.csdn.net/ehcoing/article/details/51865922 ********************************************** ...

  8. kylin的状态栏(启动器)改成ubuntu之前的样子

    ylin的状态栏(启动器)改成ubuntu之前的样子,ubuntu是在左边的,kylin在底部.占空间. 执行命令 gsettings set com.canonical.Unity.Launcher ...

  9. css按钮固定

  10. Android实例-调用GOOGLE的TTS实现文字转语音(XE7+小米2)(XE10.1+小米5)

    相关资料: 注意:在手机上必须选安装文字转语音引擎“google Text To Speech”地址:http://www.shouji56.com/soft/GoogleWenZiZhuanYuYi ...