博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java11新特性---Nest-Based Access Control(嵌套访问控制)
阅读量:6869 次
发布时间:2019-06-26

本文共 2369 字,大约阅读时间需要 7 分钟。

简介

嵌套是一种访问控制上下文,它允许多个class同属一个逻辑代码块,但是被编译成多个分散的class文件,它们访问彼此的私有成员无需通过编译器添加访问扩展方法。

动机

很多jvm语言支持在一个源文件中放多个class。这对于用户是透明的,用户认为它们在一个class中,所以希望它们共享同一套访问控制体系。为了达到目的,编译器需要经常需要通过附加的access bridge扩大private成员的访问权限到package。这种bridge和封装相违背,并且轻微的增加程序的大小,会干扰用户和工具。所以我们希望一种更直接,更安全,更透明的方式。

一个更大的坑就是反射的时候会有问题。当使用java.lang.reflect.Method.invoke从一个nestmate调用另一个nestmate私有方法时会报IllegalAccessError错误。这个是让人不能理解的,因为反射应该和源码级访问拥有相同权限。

话不多说,看段代码

public class JEP181 {    public static class Nest1 {        private int varNest1;        public void f() throws Exception {            final Nest2 nest2 = new Nest2();            //这里没问题            nest2.varNest2 = 2;            final Field f2 = Nest2.class.getDeclaredField("varNest2");           //这里在java8环境下会报错,在java11中是没问题的            f2.setInt(nest2, 2);            System.out.println(nest2.varNest2);        }    }    public static class Nest2 {        private int varNest2;    }    public static void main(String[] args) throws Exception {        new Nest1().f();    }}复制代码
在java11之前,classfile用InnerClasses和EnclosingMethod两种属性来帮助编译器确认源码的嵌套关系,每一个嵌套的类型会编译到自己的class文件中,在使用上述属性来连接其他class文件。这些属性对于jvm确定嵌套关系上已经足够了,但是它们不直接适用于访问控制,并且和java语言绑定的太紧了。

为了提供一种更大的,更广泛的,不仅仅是java语言的嵌套类型,并且补足访问控制检测的不足,引入了两个新的class文件属性。定义了两种nest member,一种叫nest host(也叫top-level class),它包含一个NestMembers属性用于确定其他静态的nest members,其他的就是nest member,它包含一个NestHost属性用于确定它的nest host。

大家可以看一下上述代码的class文件详情。

JVM针对嵌套成员的访问控制

调整了jvm访问规则,增加了如下条款:

一个field或method R可以被class或interface D访问,当且仅当如下任一条件为真:

  • … …(原条款不变)
  • R是私有的,并且声明在另一个class或interface C中,并且C和D是nestmates

C和D是nestmates表名他们肯定有一个相同的host

这个松散的访问规则会作用在如下几个地方:(这一段我就贴原文了,感觉翻译过来味道就变了)

  • Resolving fields and methods (JVMS 5.4.3.2, etc.)
  • Resolving method handle constants (JVMS 5.4.3.5)
  • Resolving call site specifiers (JVMS 5.4.3.6)
  • Checking Java language access by instances of java.lang.reflect.AccessibleObject
  • Checking access during queries to java.lang.invoke.MethodHandles.Lookup

针对上述访问规则的改变,相应的调整字节码:

  • invokespecial for private nestmate constructors,
  • invokevirtual for private non-interface, nestmate instance methods,
  • invokeinterface for private interface, nestmate instance methods; and
  • invokestatic for private nestmate, static methods

嵌套类的校验

嵌套类必须在访问前校验。校验最迟要发生在访问成员之前,最早可以发生在对class文件的校验时,或者在两者之间,比如JIT时。校验嵌套关系,需要加载nest host类,为了防止无意义的加载,这一步尽量放到最后做。

为了保证嵌套的完整性,建议禁止修改nest classfile属性

转载于:https://juejin.im/post/5baec7c85188255c5f53fa37

你可能感兴趣的文章
GitHub---(使用SSH方式)
查看>>
大规模生产计划技术管理核心理念
查看>>
阿里云HBase推出全新X-Pack服务 定义HBase云服务新标准
查看>>
驼峰设计 PPT美化
查看>>
hcl DHCP与snooping的实践操作 中有个问题
查看>>
Python Python 正则 取中括号值
查看>>
springMVC-接收数据-参数绑定
查看>>
OOM问题定位方法
查看>>
hadoop day 4
查看>>
SCVMM 2012 SP1 Beta 体验(一)安装准备
查看>>
Lync Server 2013功能部署系列之七 实现Lync Server 与Exchange Server集成的功能
查看>>
老王学Linux-NFS
查看>>
这一次,我们用最详细的方式解析Android消息机制的源码
查看>>
bash之条件判断语句及循环语句
查看>>
shell-5:case比if(elif else)方便
查看>>
R基础数据类型2DAY
查看>>
shell脚本之 if,case,for的用法
查看>>
loadrunner12--tree
查看>>
安全多方计算(MPC)从入门到精通:经典案例
查看>>
自动化运维之Ansible安装及基本模块应用
查看>>