本文主要研究下迁移到java9的一些注意事项。

迁移种类

1、代码不模块化,先迁移到jdk9上,好利用jdk9的api

2、代码同时也模块化迁移

几点注意事项

不可读类

比如sun.security.x509,在java9中归到java.base模块中,但是该模块没有export该package

可以通过运行的时候添加--add-exports java.base/sun.security.x509=ALL-UNNAMED来修改exports设定

内部类

比如sun.misc.Unsafe,原本只想让oracle jdk team来使用,不过由于这些类应用太广泛了,为了向后兼容,java9做了妥协,只是将这些类归到了jdk.unsupported模块,并没有限定其可读性。

➜ ~ java -d jdk.unsupported

jdk.unsupported@9

exports com.sun.nio.file

exports sun.misc

exports sun.reflect

requires java.base mandated

opens sun.misc

opens sun.reflect

删除的类

java9删除了sun.misc.BASE64Encoder,这种情况只能改用其他api,比如java.util.Base64

classpath vs module-path

java9引入了模块系统,同时自身的jdk也模块化了,引入了module-path,来屏蔽classpath,也就是说在java9优先使用module-path,毕竟jdk本身都模块化了,应用本身没有模块化的话,java9通过unnamed modules及automatic modules机制来隐式模块化,当然classpath在java9上还能继续使用,比如配合module-path使用等。

没有模块化的jar在classpath会被归到unnamed modules;在module-path则会被自动创建为automatic modules(一个automatic modules会声明transitive依赖所有named和unnamed module,然后导出自身的package)

一个包名不能在多个模块中出现(split packages)

因为模块中可以exports指定包给其他模块,如果多个模块exports同样的包名会造成混乱,特别若有其他类库同时requires这两个模块,就不知道该引用那个模块的了。

传递依赖

如果一个模块的接口参数或返回类型使用了其他模块的类,则建议requires transitive它依赖的模块

小心循环依赖

在设计模块的时候,要尽可能考虑到是否会有循环依赖的问题,如果有则需要重新设计

使用services来实现optional依赖

services特别适合用来解耦调用方与实现类依赖的问题,如果接口有多种实现类,调用方不必要requires所有的实现类,只需要requires接口即可,使用services类型来加载实现类的实例。通过在module-path去动态添加实现模块实现解耦。

模块版本管理

module-info.java不支持声明版本号,但是创建jar包的时候,可以通过--module-version设置。不过模块系统查找模块的时候还是使用模块名来查找(如果module-path里头有多个重名模块,则模块系统知会使用找到的第一个,自动忽略后续的同名模块),版本依赖问题不在模块系统解决范畴内,交由maven之类的依赖管理工具去管理。

模块资源访问

模块化之后资源文件也收到保护,只能由该模块去访问本模块自身的资源文件,如果需要跨模块访问,也必须借助ModuleLayer找到目标模块,再调用目标模块去加载该模块的资源文件。

反射的使用

这里涉及到deep reflection问题,所谓的deep reflection就是通过反射去调用一个class的非public元素。module-info.java的exports声明package只是允许该package直接所属的类允许访问其public元素,并不允许反射调用非public元素。

反射在模块系统里头需要特殊声明才允许使用(使用opens声明允许deep reflection),这样就导致很多使用反射的类库诸如spring,需要额外配置才能迁移到java9。解决方案有两个:一个是opens package包名给需要反射的模块,比如spring.beans等;一个就是直接opens整个模块。

默认--illegal-access=permit,同时该设置只适用于java9之前的package在java9被不允许访问,不适用于java9中新的不允许访问的package.(建议迁移到模块化系统时设置为deny)

不过就是在模块系统中包名不一样就属于不同的包,没有继承关系,比如com.service.func1与com.service.func2这两个是不同的包,你不能只opens com.service,必须分别指定这样就导致需要open的的package比较多。因此open整个module可能更省事一点,但也属于比较粗暴的做法。

上面的做法是在原来module-info.java里头去做修改,另外一种是在执行java或javac的时候通过指定的命令来修改原来的关系。比如

java ... --add-opens source-module/source-package=target-module

如果需要导出给unnamed modules,则target-module为ALL-UNNAMED

当然如果是新的系统,那就不建议使用反射了,可以使用MethodHandles及VarHandles。

常见问题和措施

ClassNotFoundException/NoClassDefFoundError

比如javax.xml.bind.JAXBException,JAXB已经归入到java.xml.bind模块,在java命名后面添加

--add-modules java.xml.bind

如果图省事,把$JAVA_HOME及所有第三方类库添加到module-path,然后来个

--add-modules ALL-MODULE-PATH

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

反射原因引起,由于旧系统没有module-info,因此在java命名添加参数加以修改

--add-opens java.base/java.lang=ALL-UNNAMED

确定依赖的模块

通过IDE或者jdeps分析

jdeps --class-path 'classes/lib/*' -recursive -summary app.jar

jdeps只是静态代码分析,如果有使用反射用的类jdeps分析不出来,需要自己手工requires,如果dependency是optional的,可以requires static

对模块单元测试的可读性问题

如果单元测试时单独模块的话,可以在运行时通过--add-exports或--add-opens来授予单元测试模块对目标模块的可读性及反射能力。另外由于split packages问题,单元测试类的包名不能跟目标模块包名重复。原来maven工程那种test

小结

可以分两步走迁移到java9,首先是先不模块化,只先跑在jdk9上;然后再模块化。

java 物体移动不了总结_java9迁移注意问题总结相关推荐

  1. Elasticsearch RestHighLevelClient 已标记为被弃用 它的替代方案 Elasticsearch Java API Client 的基础教程及迁移方案

    在Elasticsearch7.15版本之后,Elasticsearch官方将它的高级客户端RestHighLevelClient标记为弃用状态.同时推出了全新的Java API客户端Elastics ...

  2. java类功能的模块化电源_Java9模块化指南

    1. 概述 Java9在包之上引入了一个新的抽象级别,正式称为Java平台模块系统(JPMS),简称"模块". 在本文中,我们将介绍新系统并讨论其各个方面. 2. 什么是模块? 首 ...

  3. JAVA物体运动检测_基于OpenCv的运动物体检测算法

    #include #include #include #include int main( int argc, char** argv ) //声明IplImage指针 IplImage* pFram ...

  4. Spring Boot 应用迁移到 Java 11

    你的Spring Boot App需要迁移到Java 11 吗? 最近,我们开始将应用程序从Java 8迁移到Java 11;在此之前,Oracle宣布将从2019年初开始停止为Java 8提供商业支 ...

  5. java 程序迁移后oracle 数字溢出_Spring Boot 应用迁移到 Java 11

    你的Spring Boot App需要迁移到Java 11 吗? 最近,我们开始将应用程序从Java 8迁移到Java 11;在此之前,Oracle宣布将从2019年初开始停止为Java 8提供商业支 ...

  6. Hadoop离线 day18 sqoop数据迁移和java执行shell命令

    sqoop数据迁移和java执行shell命令 3. sqoop数据迁移 3.1.概述 3.2.sqoop1与sqoop2架构对比 3.3.工作机制 3.4 .sqoop实战及原理 3.4.1 sqo ...

  7. 图像也能做情感迁移?罗切斯特大学团队提出计算机视觉新任务

    点击上方,选择星标或置顶,不定期资源大放送! 阅读大概需要15分钟 Follow小博主,每天更新前沿干货 计算机视觉领域中有很多任务,如目标检测.图像转换.风格迁移等,但你听说过「图像情感迁移」吗? ...

  8. Java基础20:Java8新特性终极指南

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  9. 2019年Java和JVM生态系统预测:OpenJDK将成为Java运行时市场领导者

    本文对2019年Java和JVM生态系统做了一些预测. 正如InfoQ 2018年度总结中说的那样,Java在2018年的发展势头非常有意思. 在我们步入2019之际,让我们来看看在新的一年中Java ...

  10. 【OkHttp】OkHttp 源码分析 ( 网络框架封装 | OkHttp 4 迁移 | OkHttp 建造者模式 )

    OkHttp 系列文章目录 [OkHttp]OkHttp 简介 ( OkHttp 框架特性 | Http 版本简介 ) [OkHttp]Android 项目导入 OkHttp ( 配置依赖 | 配置 ...

最新文章

  1. 智能生产的现状与未来!
  2. shell提示符的个性化设定
  3. 车联网大数据框架_FEV:基于最新网关技术管理车联网大数据
  4. python的socks5全局代理_Python写的Socks5协议代理服务器
  5. linux网络编程--数据结构与函数原型
  6. 清华大学2019计算机录取分数线,2019年清华大学各省各批次录取分数线
  7. 六个步骤,从零开始教你搭建基于WordPress的个人博客
  8. 永恒python配合什么主武器_让Python代码更易维护的七种武器
  9. 【模糊滑模】基于模糊切换增益调节的滑模控制
  10. 解读Depth Map Prediction from a Single Image using a Multi-Scale Deep Network (1)
  11. CAD零基础入门自学教程
  12. php怎么生成缩略图,php怎么生成缩略图
  13. WinDbg分析蓝屏dump教程
  14. 微信小程序实现发送短信的功能(发送短信)
  15. pandoc如何使用自定义样式导出docx文档
  16. 如何实现通过Leaflet加载dwg格式的CAD图
  17. Flutter 吐司弹框的使用 showToast弹框(插件)
  18. ipv6访问文件服务器,开启IPv6,让你的局域网可以使用IPV6进行共享文件夹的访问...
  19. 网易有数BI在数据可视化领域的优势地位因何受到挑战?
  20. L2-003. 月饼

热门文章

  1. golang生成随机数
  2. Java中的Math函数常用方法总结
  3. PHP 获取格式化的日期和时间
  4. android备份手机号码,简单四步 完成Android手机通讯录云备份操作
  5. linux设置开机自动运行脚本的方法
  6. Oracle 11g 通过透明网关访问瀚高数据库
  7. python中输入字符串_python如何输入字符串
  8. 块截断编码图像压缩技术
  9. 网络重置后,WiFi模块没了,网络适配器感叹号
  10. 江苏大学京江学院计算机,江苏大学京江学院