javaone
JavaOne 2015看到了Project Jigsaw团队关于Java 9中的模块化的一系列讨论 。它们都是非常有趣的,并且充满了宝贵的信息,我敦促每个Java开发人员都注意它们。
除此之外,我想给社区一种搜索和引用它们的方法,因此我在这里总结一下:
- 准备JDK 9
- 模块化开发简介
- 先进的模块化开发
- 拼图项目的幕后花絮(即将上映)
我努力链接到尽可能多的外部资源,以使各个帖子简短。 播放图标将带您直接进入Oracle每天为每个房间在线播放的长达十小时的视频流中的相应点。 (很棒的格式,伙计们!)(到目前为止)他们不仅弄乱了声音,而且似乎还诉诸于低音量的单声道声音,因此请确保提高音量。
让我们以介绍为基础,并提供一些高级模块化开发和迁移建议!
总览
- 内容 :如何将应用程序和库迁移到模块系统
- 演讲者 :马克·莱因霍尔德,亚历克斯·巴克利,艾伦·贝特曼
- 链接 : 视频和幻灯片
引言
马克·雷因霍尔德(Mark Reinhold)首先强调当前的原型仍在开发中,该提案存在一些粗糙的边缘和遗漏的部分。 拼图团队花费大量时间谈论它的原因是为了传播信息并收集反馈。
因此,请尝试并提供反馈!
应用程序迁移
在演讲的第一部分中,Alex Buckley介绍了如何将应用程序迁移到模块系统。 他在假设应用程序的依赖项尚未发布为模块的情况下对此进行了讨论。 (因为如果这样的话,这将是相当简单直接的。)
自上而下的迁移
每当将JAR转换为模块时,都必须回答两个问题:
- 该模块需要什么?
- 模块输出什么?
可以在jdeps的帮助下回答第一个问题。 第二个要求模块的作者有意识地决定哪些包包含其公共API。
然后,必须按照模块化开发简介和快速入门指南中的说明将这两个答案都输入到module-info.java中。
自动模块
Buckley现在解决了他的示例的一个内在问题:如何处理尚未发布为模块的应用程序依赖项? 解决方案是自动模块 。
只需将JAR放置在模块路径而不是类路径上,它便成为自动模块。 这是一个完整的模块,但不需要更改JAR本身。 它的名称是从JAR名称派生的,并导出所有包。 它可以读取模块路径上的所有模块(通过隐式要求所有模块) 和类路径上的所有类。
这为迁移JAR文件提供了最大的兼容性。
系统结构
即使使用了一些自动模块,它们在模块路径上增加了很多优势,但情况还是比类路径要好。 那里的所有内容都可以访问其他所有内容,并且JVM只是消除了开发人员设想的任何系统结构。
编译并运行示例
该示例已编译并使用快速入门指南中涵盖的命令运行。
Buckley还演示了javac标志-modulesourcepath来启用多模块编译 。 它需要一个目录,并且期望每个模块包含一个子目录。 然后,每个模块目录都可以包含构建模块所需的源文件和其他资源。 这对应于JEP 201和
摘要
对于自上而下的迁移,可通过为应用程序的JAR创建module-info.java文件将其转换为模块。 通过将依赖项放在模块路径而不是类路径上,可以将它们转换为自动模块。
图书馆迁移
艾伦·贝特曼(Alan Bateman)从不同的角度看待同一场景。 他正在展示如何将库转换为模块,而不需要应用程序使用它们来完成。
自下而上的迁移
对于库,需要回答与应用程序模块相同的问题:
- 该模块需要什么?
- 模块输出什么?
再次, jdeps被带出回答第一个。 但是,这里的Bateman还演示了如何使用-genmoduleinfo标志生成module-info.java文件的初稿。 在这种模式下, jdeps从JAR名称中获取模块名称,需要正确的依赖关系,并简单地导出所有软件包。 然后,模块作者应确定要导出的出口。
然后,Bateman像上面和快速入门指南中所述编译和打包模块。
混合类路径和模块路径
该应用程序尚未转换为模块,这有两个含义:
- 运行它既需要类路径又需要模块路径。
- 该应用程序无法表达其依赖的模块。
在命令行上混合类和模块路径是冗长但直接的。 最重要的是,必须使用标志-addmods来指定模块系统必须根据其解析模块路径的根模块。 在正在运行的示例中,这将是新转换的库模块。
高级迁移挑战
在给出的示例中,新创建的库模块之一使用反射来访问应用程序的代码。 这是有问题的,因为模块只能从它们所依赖的模块访问代码,而显然库不能依赖于使用它们的应用程序。
解决方案是对新类java.lang.Module的addReads 。 它可用于允许调用方法的模块读取指定的模块。 要获取模块,请调用Class.getModule()。
放在一起
将这两种方法放在一起会产生一个不错的依赖关系图和启动应用程序的超短命令。
然后,Bateman继续使用jlink将生成的应用程序打包到具有jlink的最小独立运行时映像中,如模块化开发简介中所述 。
摘要
总之,这两种方法显示了应用程序和库维护者如何按照自己的进度独立地模块化他们的项目。 但是请注意,可能需要更改一些代码。
继续模块化!
问题
绝大多数问题都很有趣,所以我们开始吧。
有人可以覆盖您的安全软件包吗?
拼图团队正在制作可选验证步骤的原型。 在构建时,它将计算模块的强哈希并将其烘烤到模块中。 然后它将在启动时验证哈希。
是否可以访问未导出的类型?
不是来自代码。 如果某些类型必须以这种方式可用(例如,用于依赖项注入框架),则必须将其导出。 故意没有办法用反射破坏模块封装。
但是可以使用命令行标志-XaddExports,如JEP 261中的 “破坏封装”一节中所述。
拼图与OSGi兼容吗?
不,但是OSGi将在其之上运行。
模块可以包含DLL,SO吗?
JNI的工作原理与以前完全相同,模块可以包含各种资源,包括特定于OS的库。
为什么在module-info.java中未指定主类?
因为对于编译器和JVM而言,它不是必不可少的信息。 实际上,它甚至不是程序的必要属性,因为对于同一项目版本的不同部署,它可能会更改。
如何表达对未模块化JAR的依赖性?
该库可以要求其依赖关系,如上所示。 如果尚未将其模块化,则文档应提及它们仍必须添加到模块路径(与类路径相对)中。 然后将它们转换为自动模块,从而使它们可用于库。 当然,类路径仍然是出口,并且库始终可以放在此处,并且所有内容都像以前一样工作。
另外,如果项目之间的协作受到限制,Buckley建议使用反思。 然后,该库将不必要求其依赖关系,而是在运行时开始读取它,而不管它是放在类还是模块路径上。
那么像Maven这样的工具呢?
拼图团队希望与所有工具供应商合作以提供支持,但目前尚无计划,因为它还为时过早。
Buckley试图通过将模块系统结合到工具中作为一个分布式问题来管理期望。 Java 9发行版不应被视为所有事物必须完美协作的起点,而应被视为使一切相互协作的起点。
那(上下文)类加载器呢?
模块系统几乎与类装载机正交,并且应该没有问题的相互作用。 加载程序被描述为低级机制,而模块则是更高的抽象。
有关更多详细信息,请等待Jigsaw项目幕后的概览。
是否可以将多个模块打包到一个JAR中?
或者换句话说,是否有可能构建一个包含多个模块(通常是其所有依赖项)的fat / uber JAR?
目前尚不支持,但是创建映像可能是某些用例的解决方案。 由于这个问题反复出现,Reinhold承诺会考虑一下。
翻译自: https://www.javacodegeeks.com/2016/01/javaone-2015-advanced-modular-development.html
javaone