设为首页 加入收藏

TOP

JDK8升级JDK11最全实践干货来了(二)
2023-09-23 15:44:18 】 浏览:129
Tags:JDK8 升级 JDK11 全实践 干货来
是可以定义模块描述符来隔离module(Jar包)内部类的访问权限。

模块化的几点关键说明:

1)相对于JDK8的变动

  • JDK9以后引入了一个新组件module:模块描述符module-info.java,用于将一组相关的包放入一个组中。
  • 在Java8和更早的应用程序中,应用程序将包作为顶级组件,Java9以后应用程序将模块作为顶级组件
  • 一个模块(Jar包)只能有一个module-info.java

2)和maven的关系

模块化并不是要替代maven,和maven本身并不冲突,maven定义jar之间的依赖关系,模块化是对已经依赖的jar下的包进行更细粒度依赖控制

3)如何兼容旧应用

天然兼容旧应用。为了向后兼容旧项目,一些库本身并未模块化,其仍然可以作为模块在模块路径中使用,而这些库在模块路径上时会被转化为自动模块,例如:jackson-databind-1.0.0.jar将成为自动模块jackson.databind

6.2、带来了哪些好处?

1)封装和隔离,更好的访问控制

模块化允许开发者将代码和资源封装在独立的模块中。模块之间可以明确地定义公开和私有的API,提供了更好的代码隔离性和可维护性。

ps:新业务单应用可以按照领域模型来进行多模块的划分,以避免代码腐化。简单举例单应用下存在产品.jar、订单.jar。订单依赖产品,通过模块化的限制,订单只能使用产品中明确对外暴露的类,这样就避免传统模式订单.jar可能依赖了产品.jar中普通的类导致代码腐化的问题,也降低后续领域服务拆分的复杂度

2)更好的可伸缩性,加载速度的提升

模块化系统使得Java平台更加可伸缩,通过模块化定义,可以仅加载需要的模块,从而提升加载类的效率,最终减少了应用程序的内存占用和启动时间,同时打包后的程序也更小。

3)明确的依赖关系

模块化系统要求在模块之间明确定义依赖关系。在编译或运行代码之前,模块系统会检查模块是否满足所有依赖关系,从而导致更少的运行时错误。

4)安全

在JVM的最深层次上执行强封装,减少Java运行时的攻击面,同时无法获得对敏感内部类的反射访问。

6.3、如何使用

1)定义module-a.jar

包结构如下:

com.jdt.a
        person
            Men.java
        reflect
            ReflectModel.java
        module-info.java    




module-info文件内容如下:

module module.a { 
    //指令用于指定一个模块中哪些包下的public对外是可访问的,包括直接引入和反射使用 
    exports com.jdt.a.person; 
    // 只能被反射调用,用于指定某个包下所有的 public 类都只能在运行时可被别的模块进行反射,并且该包下的所有的类及其乘员都可以通过反射进行访问。 
    opens com.jdt.a.refect; 
}




2)定义module-b.jar,包的pom中指定依赖了module-a

包结构如下:

com.jdt.b
        test
            Test.java
        module-info.java    




module-info文件内容如下:

module module.b {
     //依赖a下的包
     requires module.a;
}




3)此时module-b.jar,在编写编码时,会遇到如下问题

6.4、实践过程的坑

上面简单介绍了模块化的知识,具体在落地过程中,我们主要踩了以下的坑,供大家参考

1)依赖JSF包时无法模块化

* JSF是京东内部使用的高性能RPC框架

进行模块化时,pom中依赖了jsf包,模块定义如下:

module module.a {
    requires  fastjson;
    //依赖jsf包名
    requires  jsf.lite;

    exports com.jd.jdk.test.module;
}




此时编译报错如下:提示找不到模块:jsf.lite,但是pom中明明指定依赖了jsf.lite

问题原因:

经过一系列定位研究,发现jsf-lite包中,/META-INF/services下的文件org.glassfish.jersey.internal.spi.AutoDiscoverable里面写的类是com.alibaba.fastjson.support.jaxrs.FastJsonAutoDiscoverable,此类并未在当前jsf.lite包中定义,属于com.alibaba.fastjson包的。

但是我们的pom中明明也依赖了com.alibaba.fastjson包,为什么模块化后,就找不到了呢?

主要原因在于模块化遇到SPI(Service Provider Interface)时的约束:模块化时,SPI机制要求配置中定义依赖的类必须本模块定义的,不能是其他模块的包(来自它不拥有的包),否则,此包将无法被模块化

这样也就解释了,为什么上面jsf无法找到module的问题,jsf-lite里面设置了它不拥有的包:com.alibaba.fastjson.support.jaxrs.FastJsonAutoDiscoverable,导致jsf-lite包无法被自动模块化

解决方案:

1、联系JSF团队,升级JSF包,修复上面说的FastJsonAutoDiscoverable配置错误的问题。

2)拆包问题(模块隔离)

模块化约束:jdk9以上,使用模块化时不支持拆分包的形式依赖

拆分包意味着两个模块包含相同的包,Java模块系统不允许拆分包。拆分包始终是不正常的,而当使用解析可传递依赖项的构建工具(如Maven等)时,很容易出现同一个库的多个版本,当Java模块系统检测到一个包存在于模块路径上的多个模块中时,就会拒绝启动。

例如:

module-a.jar包结构定义:
com.foo.package
    A.java
    
module-b.jar包结构定义:
com.foo.package
    B.java   




当module-c同时依赖module-a和module-b时,如上编译时会报一个错,Package com.foo.package in both module module.b and module module.a,这就是JAVA9的模块隔离,要求只能从一个模块(module)中读取同一个包(package),不能跨模块读取。

解决方案:

如果在使用模块化时,遇到了拆分包问题,无论如何都是无法绕过的。即使从用户角度来看基于类路径的应用程序可以正确工作,你也最终需要处理这些问题。此时只能停用模块化或升级jar包,避免拆分包问题

6.5、模块化落地总结

目前不推荐使用模块化,因为相关组件生态还不完善,并且模块化带来的价值不够突出:

  1. 很多中间件都是基于jdk8构建的,都有可能遇到模块化兼容的问题,比如:jsf,需要jsf强制升级才可以使用模块化

  2. 拆包问题无法解决,比如:aws-java-sdk-s3、fluent等。

7、总结

  1. 升级过程简单,升级后可以使用更多新特性和更好的GC性能,所以 建议升级到JDK11
  2. 现阶段 不推荐使用模块化,但是不用担心会影响JDK11的升级。

另外听说JDK17的 ZGC可以达

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇25届实习/秋招-java面试-JavaSe面.. 下一篇快速搭建SpringBoot3.x项目

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目