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. Spring Security教程(二):通过数据库获得用户权限信息

    上一篇博客中,Spring Security教程(一):初识Spring Security,我把用户信息和权限信息放到了xml文件中,这是为了演示如何使用最小的配置就可以使用Spring Securi ...

  2. Java操作XML的JAXB工具

    在java中操作XML的工作中中,比较方便的工具是JAXB(Java Architecture for XML Binding). 利用这个工具很方便生成XML的tag和Java类的对应关系.参照网上 ...

  3. HTML5学习笔记(二十二):DOM

    DOM即文档对象模型(Document Object Model),其定义了访问和操作 HTML 文档的标准方法. DOM 将 HTML 文档表达为树结构,如下: 通过DOM,开发人员可以动态的添加. ...

  4. FFmpeg(9)-解码器解码代码演示(FFmpeg调用MediaCodec实现硬解码、多线程解码、及音视频解码性能测试)

    一.AVFrame 用来存放解码后的数据. [相关函数] AVFrame *frame = av_frame_alloc();                       // 空间分配,分配一个空间 ...

  5. 乐观锁的一种实现方式—CAS

    线程安全 众所周知,Java是多线程的.但是,Java对多线程的支持其实是一把双刃剑.一旦涉及到多个线程操作共享资源的情况时,处理不好就可能产生线程安全问题.线程安全性可能是非常复杂的,在没有充足的同 ...

  6. .NET MVC5+ EF+AutoFac自动注入框架

    1.创建一个MVC系统 VIEW显示页面代码: <link href="~/Content/bootstrap.css" rel="stylesheet" ...

  7. python(40):利用utf-8编码判断中文英文字符

    #!/usr/bin/env Python # -*- coding:GBK -*- """汉字处理的工具: 判断unicode是否是汉字,数字,英文,或者其他字符. 全 ...

  8. DIOCP开源项目-Delphi高性能无锁队列(lock-free)

    最近想在DIOCP中加入任务调度线程,DIOCP的工作线程作为生产者(producer)将接受到的数据对象,投递到任务调度线程中,然后统一进行分配.然而这一切都需要一个队列, 这几天都在关注无锁队列. ...

  9. Vue右键菜单

    rightShow(item) { this.isPersoncontextMenus = true; let menu = document.getElementById("msgRigh ...

  10. fzu2158

    http://acm.fzu.edu.cn/problem.php?pid=2158 在密室逃脱游戏中,大家被困在一个密室中,为了逃出密室,需要找到正确的数字密码,于是大家分头行动,分别找到了密码的子 ...