unsafe

早上看到了文章关于Unsafe类的,就看了下根据文章看了下里面的一些操作,下面是实现的代码

public class Test {

    public static void main(String[] args) throws Exception {
        Field field111 = Unsafe.class.getDeclaredField("theUnsafe");
        field111.setAccessible(true);
        Unsafe unsafe = (Unsafe) field111.get(null);
        Demo demo=new Demo();
        Long nameadd = unsafe.objectFieldOffset(demo.getClass().getDeclaredField("name"));
//        Long nameadd = unsafe.objectFieldOffset(Demo.class.getDeclaredField("name"));
        Long ageadd = unsafe.objectFieldOffset(demo.getClass().getDeclaredField("age"));
       /* nameadd=nameadd^ageadd;
        ageadd=nameadd^ageadd;
        nameadd=nameadd^ageadd;
        Field field = Demo.class.getDeclaredField("name");
        Class<?> type = field.getType();
        System.out.println(type);*/
       Integer integer=new Integer(1);
        unsafe.putObject(demo,nameadd,"11");
        System.out.println(demo.name);
        Demo demo1=new Demo();
        unsafe.putObject(demo1,nameadd,"11222");
        System.out.println(demo1.name);

    }

}
class Demo{
     String name=new String("s");
     Integer age=new Integer(1);

}

unsafe类是 
private Unsafe() {
    }

虽然有
     public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }
但是这里就牵涉到了类加载机制的问题了
    。如果是单纯的用静态方法取获取那么会报错,(bootstrap加载除了扩展包以外的所有,比如用object.classloader返回是null,双亲委派机制为了保证类的唯一(依赖加载器),)
因此必须要用反射

原本我看到能够获取字段的偏移量,我想到的是把2个不用类型的字段利用指针呼唤位置,所以第一次我互换的nameadd和ageadd ,但是一直会报错。我以为是我操作方式不对,然后就在网上看相关的操作教程,

就有了 unsafe.putObject(demo,nameadd,“11”); 这样是可以的。

然后我想更进一步,就把参数的“11”换为 Integer类型的发现还是报错,

那可能就是必须得同一类型把

最后就是我试了下 new 一个新的demo1 ,发现里面的name仍然是最初的“s”,这个好理解,因为参数里面有个demo的实例对象,后来对于unsafe.putObject(demo1,nameadd,“11”);我发现仍然有效,后来想想可能是因为nameadd获取的是整个class文件里的字段地址值(是不是因为class文件只加载一次)

感觉是时候去学习下class文件的内容代表的含义了。。。

//这个是unsafe可以通过allocateInstance方法直接生成对象的示例,不需要通过构造函数
class Test111 {
    public static void main(String[] args) throws Exception {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
        UnsafeTest unsafeTest = (UnsafeTest) unsafe.allocateInstance(UnsafeTest.class);
        unsafeTest.show();

    }

}
class UnsafeTest{

    static {
        System.out.println("111");
    }

    private UnsafeTest(){}

    void show(){
        System.out.println("222");
    }

}

补充下额外的:

这里写图片描述

在对象头里的markOop ,通常叫做markword,

img

kalssoop 又叫做元数据指针,就是类的实例可以通过这个确认
对于64位的指针压缩压缩的就是这个
接下来的实例数据其实就是类的field字段,里面又牵涉到了java的对齐规则

参考了这个: https://blog.csdn.net/reliveIT/article/details/101161173

​ https://www.jianshu.com/p/3d38cba67f8b

下面这个是网上的代码示例,,,,但是我一直看不懂,而且对于@Contended这个注解我自己也尝试了下发现和想象的不一样

import java.lang.reflect.Field;

import sun.misc.Contended;
import sun.misc.Unsafe;

public class TypeSequence {


    @Contended
    private boolean contended_boolean;

    private volatile byte a;
    private volatile boolean b;

    @Contended
    private int contended_short;

    private volatile char d;
    private volatile short c;



    private volatile int e;
    private volatile float f;

    @Contended
    private int contended_int;

    @Contended
    private double contended_double;

    private volatile double g;
    private volatile long h;

    public static  Unsafe UNSAFE;

    static {
        try {
            @SuppressWarnings("ALL")
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            UNSAFE = (Unsafe) theUnsafe.get(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws NoSuchFieldException, SecurityException{
        System.out.println("e:int    \t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("e")));
        System.out.println("g:double \t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("g")));
        System.out.println("h:long   \t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("h")));
        System.out.println("f:float  \t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("f")));
        System.out.println("c:short  \t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("c")));
        System.out.println("d:char   \t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("d")));
        System.out.println("a:byte   \t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("a")));
        System.out.println("b:boolean\t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("b")));


        System.out.println("contended_boolean:boolean\t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("contended_boolean")));
        System.out.println("contended_short:short\t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("contended_short")));
        System.out.println("contended_int:int\t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("contended_int")));
        System.out.println("contended_double:double\t"+UNSAFE.objectFieldOffset(TypeSequence.class.getDeclaredField("contended_double")));
    }

}

我的是这个
e:int    	40
g:double 	24
h:long   	32
f:float  	44
c:short  	54
d:char   	52
a:byte   	57
b:boolean	58
contended_boolean:boolean	56
contended_short:short	12
contended_int:int	48
contended_double:double	16




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值