Java 9 distinguishes between opens and exports

order

This article focuses on some considerations for migrating to Java 9.

Migration type

Several precautions

Unreadable class

For example, sun security. X509, which is classified as Java Base module, but the module does not export the package

You can add -- add exports Java. XML at runtime base/sun. security. X509 = all unnamed to modify the exports setting

Inner class

For example, sun misc. Unsafe, originally only wanted to be used by Oracle JDK team. However, because these classes are widely used, java9 made a compromise for backward compatibility, but classified these classes into JDK Unsupported modules do not limit their readability.

Deleted class

Java9 removed sun misc. Base64encoder. In this case, you can only use other APIs, such as Java util. Base64

classpath vs module-path

Java9 introduces a modular system and its own JDK is also modular. Module path is introduced to shield the classpath, that is, module path is preferred in java9. After all, the JDK itself is modular. If the application itself is not modular, java9 implicitly modularizes through unnamed modules and automatic modules mechanisms. Of course, the classpath can continue to be used on java9, For example, it can be used with module path.

Jars without modularization will be classified as unnamed modules in the classpath; In module path, it will be automatically created as automatic modules (an automatic module will declare that transition depends on all named and unnamed modules, and then export its own package)

A package name cannot appear in multiple modules (split packages)

Because exports can be assigned to other modules in a module, if multiple modules export the same package name, it will cause confusion. In particular, if other class libraries require these two modules at the same time, we don't know which module to refer to.

Transitive dependency

If the interface parameters or return types of a module use the classes of other modules, it is recommended to require transitive the modules it depends on

Beware of circular dependency

When designing the module, we should consider whether there will be circular dependency as much as possible. If so, it needs to be redesigned

Using services to implement optional dependencies

Services is especially suitable for decoupling the dependency between the caller and the implementation class. If the interface has multiple implementation classes, the caller does not need to require all the implementation classes, but only the requires interface. The services type is used to load the instance of the implementation class. Decoupling is realized by dynamically adding modules in module path.

Module version management

module-info. Java does not support declaring version numbers, but you can set them through -- module version when creating jar packages. However, when the module system looks for a module, it still uses the module name (if there are multiple modules with duplicate names in the module path, the module system will notify to use the first module found and automatically ignore the subsequent modules with the same name). The version dependency problem is not within the scope of the module system, but is managed by dependency management tools such as Maven.

Module resource access

After modularization, the resource file is also protected. Only the module can access the resource file of the module itself. If cross module access is required, you must also find the target module with the help of modulelayer, and then call the target module to load the resource file of the module.

Use of reflection

This involves the problem of deep reflection. The so-called deep reflection is to call the non-public elements of a class through reflection. module-info. Java exports declares that a package only allows the class directly belonging to the package to access its public elements, and does not allow reflection calls to non-public elements.

Reflection in the module system requires special declarations before it can be used (deep reflection is allowed with the opens declaration), which leads to many class libraries using reflection, such as spring, requiring additional configuration before they can be migrated to java9. There are two solutions: one is to give the package name of the opens package to modules that need reflection, such as spring Beans et al; One is to directly open the whole module.

The default -- illegal access = permit, and this setting is only applicable to packages before java9, which are not allowed to access in java9, and not applicable to new packages in java9 (it is recommended to set deny when migrating to a modular system)

However, in the module system, different package names belong to different packages, and there is no inheritance relationship, such as com service. Func1 and com service. Func2 these two are different packages. You can't just open com Services must be specified separately, which leads to a large number of packages that need to be opened. Therefore, opening the whole module may be easier, but it is also a rough approach.

The above method is based on the original module info The other is to modify the original relationship through the specified command when executing Java or javac. such as

If you need to export to unnamed modules, the target module is all unnamed

Of course, if it is a new system, reflection is not recommended. You can use methodhandles and varhandles.

Common problems and measures

ClassNotFoundException/NoClassDefFoundError

For example, javax xml. bind. Jaxbexception and JAXB have been classified into Java xml. Bind module, added after Java Naming

If you want to save trouble, put $Java_ Home and all third-party class libraries are added to module path, and then a

illegal reflective access by xxx to method java. lang.ClassLoader. defineClass

It is caused by reflection. Since the old system does not have module info, add parameters in Java Naming to modify it

Identify dependent modules

Through ide or jdeps analysis

Jdeps is only static code analysis. If there are classes for reflection that cannot be analyzed by jdeps, you need to manually require them. If dependency is optional, you can require static

Readability of module unit test

If the unit test module is a separate module, you can grant the readability and reflection ability of the unit test module to the target module through -- add exports or -- add opens at run time. In addition, due to the split packages problem, the package name of the unit test class cannot be the same as the package name of the target module. The original Maven project

Summary

You can migrate to Java 9 in two steps. First, do not modularize, but only run on jdk9; Then modular.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>