java11新特性---Nest-Based Access Control(嵌套访问控制)

栏目: Java · 发布时间: 6年前

内容简介:嵌套是一种访问控制上下文,它允许多个class同属一个逻辑代码块,但是被编译成多个分散的class文件,它们访问彼此的私有成员无需通过编译器添加访问扩展方法。很多jvm语言支持在一个源文件中放多个class。这对于用户是透明的,用户认为它们在一个class中,所以希望它们共享同一套访问控制体系。为了达到目的,编译器需要经常需要通过附加的access bridge扩大private成员的访问权限到package。这种bridge和封装相违背,并且轻微的增加程序的大小,会干扰用户和工具。所以我们希望一种更直接

简介

嵌套是一种访问控制上下文,它允许多个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");
           //这里在 java 8环境下会报错,在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属性


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Computers and Intractability

Computers and Intractability

M R Garey、D S Johnson / W. H. Freeman / 1979-4-26 / GBP 53.99

This book's introduction features a humorous story of a man with a line of people behind him, who explains to his boss, "I can't find an efficient algorithm, but neither can all these famous people." ......一起来看看 《Computers and Intractability》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具