『Java安全』Unsafe类

本文深入探讨Java中Unsafe类的功能和使用方法,包括如何获取Unsafe实例、利用Unsafe绕过构造器实例化类、定义类以及抛出任意错误等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

jdk版本基于8u111

简介

https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/misc/Unsafe.java

Unsafe类提供一些低级、不安全的操作,调用前必须确保安全。使用Unsafe可以进行类定义、类实例化、修改内存等操作。

在这里插入图片描述

警告

Unsafe抛出的任何错误都是jvm级别,会导致JVM崩溃的错误,而不是普通异常

在这里插入图片描述

unsafe类的获取

Unsafe的自动实例化在自身的静态代码块

在这里插入图片描述
仅拥有一个private构造器,getter有严格验证:只允许根加载器调用该方法

在这里插入图片描述
因此可以考虑反射获取,常规两种方式:调构造器或者调getter

        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe1 = (Unsafe) f.get(null);

        Constructor constructor = Unsafe.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Unsafe unsafe2 = (Unsafe) constructor.newInstance();

常用方法

不调用构造器实例化类

Unsafe.allocateInstance(Class<?> cls)方法提供绕过任意构造器实例化的功能
在这里插入图片描述

		Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe1 = (Unsafe) f.get(null);

        TestAllocateInst testAllocateInst = (TestAllocateInst) unsafe1.allocateInstance(TestAllocateInst.class);
package unsafeTest;

public class TestAllocateInst {

    public TestAllocateInst() {
        System.out.println("Constructor");
    }
}

运行并未触发构造器

在这里插入图片描述

defineClass定义类

绕过安全检查直接向jvm注册类

在这里插入图片描述
传入六个参数:类名、字节码、字节码起始、字节码长度、加载器、保护域

package unsafeTest;

import sun.misc.Unsafe;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;

public class TestDefine {
    public static void main(String[] args) throws Exception{
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        
        FileInputStream fis = new FileInputStream(new File("src//main//java//unsafeTest//TestAllocateInst.class"));
        byte[] bytes = new byte[fis.available()];
        fis.read(bytes);

        ClassLoader clazzLoader = ClassLoader.getSystemClassLoader();
        ProtectionDomain domain = new ProtectionDomain(
                new CodeSource(null, (Certificate[]) null), null, clazzLoader, null
        );
        
        Class clazz = unsafe.defineClass("TestAllocateInst", bytes, 0, bytes.length, clazzLoader, domain);
    }
}

在这里插入图片描述

抛出任意错误

在这里插入图片描述
在这里插入图片描述

获取内存信息

在这里插入图片描述

参考

https://javasec.org/javase/Unsafe

欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://ho1aas.blog.csdn.net/article/details/126928128
版权声明:本文为原创,转载时须注明出处及本声明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值