专栏首页码匠的流水账java9系列(七)Variable Handles

java9系列(七)Variable Handles

## 序

本文主要研究下[JEP 193: Variable Handles](http://openjdk.java.net/jeps/193)

## Variable Handles

Variable Handles的API主要是用来取代java.util.concurrent.atomic包以及sun.misc.Unsafe类的功能。一个variable handle是一个variable的类型引用,用来在一系列访问模式下来读写variable。支持的variable包括实例变量,静态成员,数据元素等。Variable Handles需要依赖jvm的增强及编译器的协助,即需要依赖java语言规范及jvm规范的升级。

## 实例

### 目标类

```

public static class Demo {

public int count = 1;

protected long sum = 100;

private String name = "init";

public int[] arrayData = new int[]{3,5,7};

@Override

public String toString() {

return "Demo{" +

"name='" + name + '\'' +

", count=" + count +

", sum=" + sum +

", data=" + Arrays.toString(arrayData) +

'}';

}

}

```

### 访问public成员

```

@Test

public void testSetPublicField() throws NoSuchFieldException, IllegalAccessException {

Demo instance = new Demo();

VarHandle countHandle = MethodHandles.lookup()

.in(Demo.class)

.findVarHandle(Demo.class, "count", int.class);

countHandle.set(instance,99);

System.out.println(instance.count);

}

```

输出

```

99

```

### 访问proteced成员

```

@Test

public void testSetProtectedField() throws NoSuchFieldException, IllegalAccessException {

Demo instance = new Demo();

VarHandle countHandle = MethodHandles.lookup()

.in(Demo.class)

.findVarHandle(Demo.class, "sum", long.class);

countHandle.set(instance,99999);

System.out.println(instance);

}

```

输出

```

Demo{name='init', count=1, sum=99999, data=[3, 5, 7]}

```

### 访问private成员

```

@Test

public void testSetPrivateField() throws NoSuchFieldException, IllegalAccessException {

Demo instance = new Demo();

VarHandle countHandle = MethodHandles.privateLookupIn(Demo.class,MethodHandles.lookup())

.findVarHandle(Demo.class, "name", String.class);

countHandle.set(instance,"hello world");

System.out.println(instance);

}

```

输出

```

Demo{name='hello world', count=1, sum=100, data=[3, 5, 7]}

```

### 访问数组类型

```

@Test

public void testSetArray(){

Demo instance = new Demo();

VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class);

arrayVarHandle.compareAndSet(instance.arrayData,0,3,100);

arrayVarHandle.compareAndSet(instance.arrayData,1,5,300);

System.out.println(instance);

}

```

输出

```

Demo{name='init', count=1, sum=100, data=[100, 300, 7]}

```

## access modes

主要的访问模式有如下几种:

### read access modes

>such as reading a variable with volatile memory ordering effects;

>主要有如下几个方法:get, getVolatile, getAcquire, getOpaque.

- get

>with memory semantics of reading as if the variable was declared non-{@code volatile}. Commonly referred to as plain read access.

- getVolatile

>用于读取volatile修饰的变量

- getAcquire

>ensures that subsequent loads and stores are not reordered before this access.

- getOpaque

>accessed in program order, but with no assurance of memory ordering effects with respect to other threads.

### write access modes

>such as updating a variable with release memory ordering effects;

>主要有如下几个方法:set, setVolatile, setRelease, setOpaque.

### atomic update access modes

>such as a compare-and-set on a variable with volatile memory order effects for both read and writing;

>主要有如下几个方法:compareAndSet, weakCompareAndSetPlain, weakCompareAndSet, weakCompareAndSetAcquire, weakCompareAndSetRelease, compareAndExchangeAcquire, compareAndExchange, compareAndExchangeRelease, getAndSet, getAndSetAcquire, getAndSetRelease.

### numeric atomic update access modes

>such as get-and-add with plain memory order effects for writing and acquire memory order effects for reading.

>主要有如下几个方法:getAndAdd, getAndAddAcquire, getAndAddRelease

### bitwise atomic update access modes

>such as get-and-bitwise-and with release memory order effects for writing and plain memory order effects for reading.

>主要有如下几个方法:getAndBitwiseOr, getAndBitwiseOrAcquire, getAndBitwiseOrRelease, getAndBitwiseAnd, getAndBitwiseAndAcquire, getAndBitwiseAndRelease, getAndBitwiseXor, getAndBitwiseXorAcquire, getAndBitwiseXorRelease.

## 小结

java9废弃了sun.misc.Unsafe类,引入了VarHandle作为替代。关于access modes部分涉及了JVM的内存模型,需要了解内存可见性、指令重排序等,才能使用好相关api。

## doc

- [JDK 9 features](http://openjdk.java.net/projects/jdk9/)

- [JEP 193: Variable Handles](http://openjdk.java.net/jeps/193)

- [VarHandle](https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/VarHandle.html)

- [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles)

- [Java 9 series: Variable Handles](https://www.voxxed.com/2016/11/java-9-series-variable-handles/)

- [Variable Handle In Java 9](https://www.javagists.com/variable-handle-java9)

- [Correct way to use VarHandle in Java 9?](https://stackoverflow.com/questions/43558270/correct-way-to-use-varhandle-in-java-9)

- [Java 9 Variable Handles](http://eppleton.de/news/java-9-variable-handles_2017-06-01.html)

本文分享自微信公众号 - 码匠的流水账(geek_luandun)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 聊聊nacos的DelegateConsistencyServiceImpl

    本文主要研究一下nacos的DelegateConsistencyServiceImpl

    codecraft
  • 聊聊dubbo-go的apolloConfiguration

    dubbo-go-v1.4.2/config_center/apollo/impl.go

    codecraft
  • 聊聊eureka server的response cache

    eureka-core-1.8.8-sources.jar!/com/netflix/eureka/resources/ApplicationResource....

    codecraft
  • c++ 实现hashmap

    由于hashmap不是c++ stl中标准实现,这样在跨平台使用时就可能会出现问题,于是想到自己实现一个hashmap hash算法使用开链法解决hash冲突,...

  • NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

      随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经显得力不从心,暴露了...

    Edison Zhou
  • 小白博客 Linux安装JDK详细步骤

    Linux安装JDK步骤 1. 先从网上下载jdk(jdk-1_5_0_02-linux-i586.rpm) ,推荐SUN的官方网站www.sun.com...

    奶糖味的代言
  • 手把手教你在腾讯云上搭建hive3.1.2的方法

    所有操作开始前,先确定hadoop版本已经装好。具体可以看我的另一篇博客 搭建hadoop3.x

    砸漏
  • Redis简介以及NoSQL概念

    相对于传统的关系型数据库,redis是另一种非关系型数据库,想要掌握redis则需要理解nosql概念以及认知redis相关事项。

    Devops海洋的渔夫
  • 服务蓝图再思考 | 洞见

    服务蓝图(Service Blueprint)是服务设计中重要的实践之一,本文将回到这一实践的本源,重新思考其核心逻辑在新的消费环境中是否需要演进。 溯源 服务...

    ThoughtWorks
  • Redis为什么会这么快?

    Redis 属于键值(key-value)数据库,键值数据库会使用哈希表存储键值和数据,其中 key 作为唯一的标识,而且 key 和 value 可以是任何的...

    MickyInvQ

扫码关注云+社区

领取腾讯云代金券