Java中邪恶的Unsafe,一半天使一半魔鬼-刘宇( 二 )

c);//定义一个类 , 此方法会跳过JVM的所有安全检查 , 默认情况下 , ClassLoader(类加载器)和ProtectionDomain(保护域)实例来源于调用者public native Class defineClass(String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain);//定义一个匿名类public native Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches);
5、对象操作
// 返回对象成员属性在内存地址相对于此对象的内存地址的偏移量public native long objectFieldOffset(Field f);// 获得给定对象的指定地址偏移量的值 , 与此类似操作还有:getInt , getDouble , getLong , getChar等public native Object getObject(Object o, long offset);// 给定对象的指定地址偏移量设值 , 与此类似操作还有:putInt , putDouble , putLong , putChar等public native void putObject(Object o, long offset, Object x);// 从对象的指定偏移量处获取变量的引用 , 使用volatile的加载语义public native Object getObjectVolatile(Object o, long offset);// 存储变量的引用到对象的指定的偏移量处 , 使用volatile的存储语义public native void putObjectVolatile(Object o, long offset, Object x);// 有序、延迟版本的putObjectVolatile方法 , 不保证值的改变被其他线程立即看到 。只有在field被volatile修饰符修饰时有效public native void putOrderedObject(Object o, long offset, Object x);// 绕过构造方法、初始化代码来创建对象public native Object allocateInstance(Class cls) throws InstantiationException;
6、内存屏障
// 内存屏障 , 禁止load操作重排序 。屏障前的load操作不能被重排序到屏障后 , 屏障后的load操作不能被重排序到屏障前public native void loadFence();// 内存屏障 , 禁止store操作重排序 。屏障前的store操作不能被重排序到屏障后 , 屏障后的store操作不能被重排序到屏障前public native void storeFence();// 内存屏障 , 禁止load、store操作重排序public native void fullFence();

Java中邪恶的Unsafe,一半天使一半魔鬼-刘宇

文章插图
7、系统相关
// 返回系统指针的大小 。返回值为4(32位系统)或 8(64位系统) 。public native int addressSize();// 内存页的大小 , 此值为2的幂次方 。public native int pageSize();
四、邪恶的 1、通过绕过构造函数
虽然可以绕过对象的构造函数 , 但不能绕过代码块
package com.test.unsafe;import sun.misc.Unsafe;import java.io.*;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.util.HashSet;import java.util.Set;public class UnsafeFooTest {public static void main(String[] args) throws InstantiationException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Unsafe unsafe = getUnsafe();//通过unsafe绕过构造函数 , 但不能绕过static代码块Simple simple = (Simple)unsafe.allocateInstance(Simple.class);System.out.println(simple.get());}static class Simple{private long i = 0;static{System.out.println("静态代码块被执行");}public Simple() {i=1;System.out.println("构造函数被执行");}public long get(){return i;}}//获取Unsafe实例private static Unsafe getUnsafe(){Field field = null;Unsafe unsafe = null;try {field = Unsafe.class.getDeclaredField("theUnsafe");field.setAccessible(true);unsafe = (Unsafe) field.get(null);} catch (Exception e) {e.printStackTrace();}return unsafe;}}