概述:按理说jdk8的unsafe类就够用了,估计是因为不安全的原因,到jdk9出了个varhandle类,到jdk21的时候出了Arena和MemorySegment,基本就可以取代unsafe类的使用了。这里我主要讲varhandle类,因为大部分人升级jdk顶多升到jdk17。
VarHandle 本身不能直接创建对象,它主要用于操作已经存在的对象。要使用 VarHandle,你需要先有一个对象实例,然后通过 MethodHandles.lookup().findVarHandle() 方法获取该对象的 VarHandle。
varhandle
是Java 9中引入的一个新特性,用于更高效地访问对象字段。它提供了一种低级别的、直接的方式来操作对象的字段,而不需要通过反射。varhandle
的主要优点是性能更好,因为它可以直接访问内存,而不需要在Java堆和本地堆之间复制数据。
实际操作
package org.cyl.spaceutils.varhandle;
import org.cyl.spaceutils.pojo.Human;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
public class VarHandleTest {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Human human=new Human();
VarHandle xvarHandle = MethodHandles.lookup().findVarHandle(Human.class, "age", int.class);
VarHandle yvarHandle = MethodHandles.lookup().findVarHandle(Human.class, "name", String.class);
xvarHandle.set(human,18);
yvarHandle.set(human,"zhangsan");
System.out.println("name:"+yvarHandle.get(human));
System.out.println("age:"+xvarHandle.get(human));
System.out.println(human);
}
}
human类代码
package org.cyl.spaceutils.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Human {
public String name;
public int age;
}
引入依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
</dependencies>
运行结果
上述代码讲解
- 创建了一个
Human
对象实例,即human
。 - 使用
MethodHandles.lookup().findVarHandle()
方法获取Human
类的两个字段的VarHandle
实例:xvarHandle
用于操作age
字段(int类型)。yvarHandle
用于操作name
字段(String类型)。
- 使用
xvarHandle.set()
方法将human
对象的age
字段设置为18。 - 使用
yvarHandle.set()
方法将human
对象的name
字段设置为"zhangsan"。 - 使用
yvarHandle.get()
方法获取human
对象的name
字段值,并打印输出。 - 使用
xvarHandle.get()
方法获取human
对象的age
字段值,并打印输出。 - 最后,打印输出
human
对象,它的toString()
方法将会被调用。
使用VarHandle
可以实现对字段的原子操作,而无需使用synchronized
关键字或java.util.concurrent.atomic
包中的原子类。