在使用Java 17(JDK 17)时,您可能需要使用--add-opens
选项来打开某些模块的包,以便让非模块化代码或其他模块能够访问这些包中的受保护成员(如protected
修饰符的方法或字段)。这是因为Java 9引入了模块系统(JPMS,Java Platform Module System),它默认情况下限制了对模块包的访问。
--add-opens
选项的作用
--add-opens
选项允许您指定应该打开哪些包,以供其他模块或非模块化的代码访问。这对于那些依赖于反射或使用内部API的应用程序特别有用。
使用--add-opens
的原因
-
模块系统的默认行为:
- Java 9及以后版本引入了模块系统,模块默认不会开放其包给其他模块或非模块化的代码访问。
- 这意味着即使是
protected
级别的成员也不会被非模块化的代码所访问,除非显式地打开相应的包。
-
反射的需求:
- 如果您的应用程序使用了反射来访问某些类的成员,那么可能需要通过
--add-opens
来打开相应的包,以便反射能够正常工作。 - 例如,如果您需要反射地调用某个类的
protected
方法或访问其protected
字段。
- 如果您的应用程序使用了反射来访问某些类的成员,那么可能需要通过
-
兼容性需求:
- 如果您的应用程序或库依赖于访问某些内部API,而这些API位于标准Java库的包中,那么您需要使用
--add-opens
来确保这些API仍然可用。 - 这种情况常见于那些使用内部API进行高级定制或集成的应用程序。
- 如果您的应用程序或库依赖于访问某些内部API,而这些API位于标准Java库的包中,那么您需要使用
示例命令
假设您需要访问java.lang.reflect
包中的protected
成员,您可以使用如下命令:
java --add-opens java.base/java.lang.reflect=ALL-UNNAMED -jar your-application.jar
这里的java.base/java.lang.reflect=ALL-UNNAMED
指定了要打开的包及其访问级别。ALL-UNNAMED
意味着这个包对所有未命名的模块(即非模块化的代码)都是可访问的。
注意事项
- 使用
--add-opens
可能会降低应用程序的安全性和稳定性,因为它允许访问原本不应公开的内部API。 - 如果可能的话,最好重构代码以避免使用受保护的成员或内部API,或者考虑将您的代码模块化并与Java平台模块系统更好地配合。