首页 > 编程语言 >java的unsafe类和varhandle类

java的unsafe类和varhandle类

时间:2023-12-07 14:11:24浏览次数:40  
标签:java int Unsafe unsafe import Message varhandle class

1、如何从unsafe类获取对象

private Unsafe() {
}

@CallerSensitive
public static Unsafe getUnsafe() {
Class<?> caller = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(caller.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
从中可以看出,无法直接new出来,并且getUnsafe方法也不是给我们使用的。

2、用反射的方式从unsafe类中获取对象

由于源码里面有

private static final Unsafe theUnsafe;

所以我们可以使用:

public static Unsafe reflectGetUnsafe(){
try {
Field unsafe = Unsafe.class.getDeclaredField("theUnsafe");
unsafe.setAccessible(true);
return (Unsafe) unsafe.get(null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

3、拿到了unsafe能做什么?

1、它能修改对象地址里面的元素信息

2、它可以自己开辟一段空间用来存东西

3、它提供了原子类修改方法

4、它可以绕开java的构造器来创建对象

package memory.unsafeTest;

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class UnsafeTest {
public static void main(String[] args) throws InstantiationException {
Unsafe unsafe = reflectGetUnsafe();
Message message=new Message(1,"你好");
int anInt = unsafe.getInt(message, 0);
System.out.println(anInt);
long address = unsafe.allocateMemory(4); // 分配4个字节的内存空间
unsafe.putInt(address, 21); // 将值存储到该地址上
System.out.println(unsafe.getInt(address)); // 输出:21

Message demo = (Message) unsafe.allocateInstance(Message.class);
System.out.println(demo.id); // 输出:0

unsafe.freeMemory(address); // 释放内存空间

}

public static Unsafe reflectGetUnsafe(){
try {
Field unsafe = Unsafe.class.getDeclaredField("theUnsafe");
unsafe.setAccessible(true);
return (Unsafe) unsafe.get(null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

Message类:

package memory.unsafeTest;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Message {
public int id=9;
public String name;
}

输出结果:

 

4、那varhandle类有什么用?

因为unsafe是不安全的且只许那些编程java的人写,所以就搞了一种更安全的类,此类可以让所有人使用

具体用法:

VarHandle xHandle = MethodHandles.lookup().in(Message.class).findVarHandle(Message.class, "id", int.class);

这个方法的作用是获取Message类中名为"id"的int类型变量的VarHandle对象。VarHandle是Java 9中引入的一种新的机制,用于在不使用反射的情况下直接访问Java对象的字段和数组元素。通过VarHandle,可以实现对变量的原子性操作,而不需要使用synchronized或者Lock等同步机制。在这个例子中,通过xHandle可以直接访问Message类中的"id"变量,从而实现对该变量的原子性操作。

为什么都要提原子操作呢?因为这个类发明的初衷就是:

随着 Java 中的并发和并行编程的不断扩展,程序员 由于无法使用 Java 结构来安排,他们越来越感到沮丧 对单个类的字段进行原子或有序操作;例如 以原子方式递增字段。到目前为止,实现的唯一方法 这些效果是使用独立的(添加两个空间 间接管理的开销和其他并发问题)或在某些方面 情况,使用原子 s(经常遇到更多的开销 比操作本身),或者使用不安全的(和不可移植的和 不支持)用于 JVM 内部函数的 API。内部函数更快, 因此,它们已被广泛使用,损害了安全性和便携性。countAtomicIntegerFieldUpdatersun.misc.Unsafe

如果没有这个 JEP,这些问题预计会随着原子 API 而变得更糟 展开以涵盖其他访问一致性策略(与最近的 C++ 内存模型)作为 Java 内存模型修订版的一部分

 参考: JEP 193:可变句柄 (openjdk.org)                                                                                                                                            

5、如何使用varhandle类

package memory.varhandleTest;

import memory.unsafeTest.Message;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;

public class VarHandleTest {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
// 获取VarHandle对象
VarHandle xHandle = MethodHandles.lookup().in(Message.class).findVarHandle(Message.class, "id", int.class);
System.out.println(xHandle);
// 创建Message对象
Message message = new Message();
// 获取id字段的值
int o = (int)xHandle.get(message);
// 将id字段的值设置为2
xHandle.set(message, 2);
// 再次获取id字段的值
int i = (int)xHandle.get(message);
// 打印结果
System.out.println(o);
System.out.println(i);
}
}

 结果:

 它里面的原子操作:

比如说getVolatile这个方法和setVolatile这个方法到底是不是原子操作,就交由你们完成了0.0

标签:java,int,Unsafe,unsafe,import,Message,varhandle,class
From: https://www.cnblogs.com/nanshaws/p/17881782.html

相关文章

  • Java开发者必备:Maven简介及使用方法详解!
    今天我们来介绍一个在Java开发中非常重要的工具——Maven。如果你是一名Java开发者,那么你一定不会对Maven感到陌生。但是,对于一些新手来说,可能还不太了解Maven是什么,它有什么作用,以及如何使用它。接下来,就让我们一起来深入了解一下Maven吧!一、maven简介Maven是什么Maven是一个......
  • 高级实现Java的七大热门技术框架解析源码特性分析
    设计模式是软件开发中常用的解决方案,可以帮助我们构建灵活可扩展的应用程序。本文将深入探讨Java的七大经典设计模式,并提供相关示例代码。一、单例模式单例模式确保一个类只有一个实例,并提供全局访问点。以下是一个简单的单例模式示例代码:publicclassSingleton{privatesta......
  • Spring Boot:Java开发者的新伙伴
    SpringBoot是一款由Pivotal团队开发的开源框架,它是Spring框架的扩展,旨在简化新生成的Spring应用程序的配置和部署。SpringBoot让Spring应用的创建更容易,因为它消除了许多样板代码和配置文件的必要性。一、SpringBoot的核心概念1.自动配置SpringBoot的自动配置特性是其吸引人......
  • Windows 下部署Redis 主从模式+哨兵模式+JAVA连接方式
    原文:Windows下部署Redis主从模式+哨兵模式+JAVA连接方式_javaredis部署-CSDN博客前言之前项目需求部署redis高可用,走了很多弯路以及相关配置来回折腾浪费了很多时间,特地记录下。主从模式:实现多台redis实例进行服务运行,并且数据相互同步;哨兵模式:实现主服务器和从服务器进行监......
  • java基本数据类型
    数据类型名称位数默认值最小值最大值byte 1字节(8位) 0 -128127 short2字节(16位) 0  -3276832767 int4字节(32位) 0  -2^31 2^31-1long8字节(64位)0L  -2^632^63-1 float4字节 0.0F   double8字节 0.0   ......
  • Maven无法下载fastdfs-client-java依赖问题解决
    一、分析原因控制台报错具体如下:并且pom.xml中以下依赖爆红:<dependency><groupId>org.csource</groupId><artifactId>fastdfs-client-java</artifactId><version>1.29-SNAPSHOT</version></dependency>原因:因为fastdfs-clien......
  • 21207119-第三次java博客
    前言第三次博客,主要是成绩系统和期末考试题量:不是太大,小题写的会快些,但是系列题找测试点的过程有时候很费时间难度:中等偏上,包含了诸多细节和需求,包括各种异常处理和特殊情况的处理测试与分析7-1容器-HashMap-检索分数10全屏浏览题目切换布局作者 蔡......
  • Golang unsafe.Pointer类型代码示例
    指针类型基本代码示例在Go语言中,指针类型用于存储变量的内存地址。通过指针,我们可以直接访问和修改变量的值。下面是一些关于指针类型的示例代码:packagemainimport"fmt"funcmain(){//声明一个整数变量并赋值num:=10fmt.Println("原始值:",num)/......
  • Golang unsafe.Sizeof 函数代码示例
    在Go语言中,可以使用unsafe.Sizeof()函数来获取变量或类型的大小(以字节为单位)。下面是一个示例代码,演示如何使用unsafe.Sizeof()函数:packagemainimport( "fmt" "unsafe")typePersonstruct{ Namestring Ageint}funcmain(){ varnumint varstrstring......
  • java云HIS系统源码 区域HIS信息管理系统源码
    医院管理信息系统(HIS)是医院基本、重要的管理系统,是医院大数据的基础。“云”指系统采用云计算的技术和建设模式,具有可扩展、易共享、区域化、易协同、低成本、易维护、体验好的优势。“H”是医疗卫生,由原来医院(Hospital)到现在的医疗卫生(Healthcare),拓展了H的内涵与外延。云......