为什么 getClass().getName() 在未打开的模块 class 上工作?

Why does getClass().getName() work on a module class that is not open?

我有两个 Java 9 模块、一个服务器和一个处理程序。服务器使用 ServiceLoader(下面的代码)加载 HTTP 处理程序。

为什么此代码段中的 o.getClass().getName() 有效?是因为“提供”打开了处理程序 class 以进行反射吗? getClass().getName() 不使用反射吗? Java 是否总能在不需要反射的情况下将接口映射到底层 class 实例(从而映射到 class)?

服务器模块代码:

    ServiceLoader
      .load(HTTPHandlerWithContext.class)
      .stream()
      .map(ServiceLoader.Provider::get)
      .forEach(o -> {
        System.out.printf(
          "registering route %s to %s%n",
          o.getContext(),
          o.getClass().getName()
        );
        server.createContext(o.getContext(), o);
      });

处理程序模块信息:

module com.example.helloworld {
  requires com.example.tinyjhttpd;
  requires jdk.httpserver;
  provides com.example.tinyjhttpd.HTTPHandlerWithContext
    with com.example.helloworld.HelloWorld;
}

我认为 Class.java 中的相关片段不足以让我明白:

    // Cache the name to reduce the number of calls into the VM.
    // This field would be set by VM itself during initClassName call.
    private transient String name;
    private native String initClassName();

Java 语言规范没有详细定义反射(因此,opens 的影响或缺乏反射)而是 refers to the API specification:

[...] This specification constrains the behavior of such classes and interfaces, but does not provide a complete specification for them. The reader is referred to the Java SE Platform API documentation.

Consequently, this specification does not describe reflection in any detail. Many linguistic constructs have analogs in the Core Reflection API (java.lang.reflect) and the Language Model API (javax.lang.model), but these are generally not discussed here.

Java SE 平台 API 文档指定了何时可以抛出 IllegalAccessException,例如关于 Field.get or Method.invoke.

的调用

未指定 Object.getClass() nor Class.getName() 可能引发 IllegalAccessException

这与引入模块系统之前Java的运行时行为一致。只是关于何时授予或不授予访问权限的规则变得更加复杂。

与访问内部数据或调用非 API 方法相比,能够查询 class 名称的影响相当低。