为什么未开放的Java模块类调用getClass().getName()可正常运行?
问题解答
首先直接给出结论:o.getClass().getName()可以正常运行和provides关键字的反射开放权限完全无关,核心原因如下:
- 第一,
Object.getClass()是所有Java类都继承的公共原生方法,不受模块访问权限限制
你拿到的o是已经被ServiceLoader实例化完成的对象,所有对象的对象头里都存储了对应的运行时类元数据指针,getClass()只是把JVM层面绑定的类元数据返回为Class对象,这个过程不属于Java层面的反射操作,不需要任何额外的模块开放权限。 - 第二,
Class.getName()是Class类的公共方法,只要拿到Class对象就能直接调用
你贴的JDK源码也能看到,getName()要么直接返回已经缓存的name字段,要么调用本地方法initClassName()从JVM的类元数据里读取类名,这个操作既不需要反射,也不会受模块访问控制的约束。 - 第三,
provides关键字的作用仅仅是声明服务实现,本身没有开放反射权限的作用provides ... with ...只是告诉模块系统当前模块提供了某接口的具体实现,让ServiceLoader可以找到、加载并实例化这个实现类。如果你要在server模块里通过反射调用HelloWorld类的私有成员,哪怕有provides声明也会报错,必须要handler模块主动用opens关键字把对应包开放给server模块才可以。
你提到的三个疑问里正确的是后两个的组合:getClass().getName()本身不使用Java层面的反射机制,同时JVM会将每个实例和它的底层类元数据直接绑定,不需要额外通过反射映射接口和实现类就能拿到类信息。
内容的提问来源于stack exchange,提问作者user1789168
相关产品推荐
相关产品推荐

