前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解JVM(③)Java的模块化

深入理解JVM(③)Java的模块化

作者头像
纪莫
发布2020-07-02 10:20:05
1.1K0
发布2020-07-02 10:20:05
举报
文章被收录于专栏:Jimoer

前言

JDK9引入的Java模块化系统(Java Platform Module System ,JPMS)是 对Java技术的一次重要升级,除了像之前JAR包那样充当代码的容器之外,还包括:

  • 依赖其他模块的列表。
  • 导出的包列表,即其他模块可以使用的列表。
  • 开放的包列表,即其他模块可反射访问模块的列表。
  • 使用的服务列表。
  • 提供服务的实现列表。

模块化系统

可配置的封装隔离机制解决了原来类路径上跨文件的public类的可访问性的问题。public类型不再意味着所有地方代码都可以访问它们,未导出未开放的类是不能够被外部使用。

举例说明:

新创建一个maven工程,并创建两个module。

在每个module的Language level 和 SDK 设置成JDK9

然后在每个module的顶层目录中创建module-info.java

在ExampleOne中创建两个不同package下的类,ExampleFirstExampleOne

代码语言:javascript
复制
package com.jimoer.jdkmoduleOne.test;

public class ExampleFirst {

    private int id;

    private String name;

    private String sex;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "ExampleFirst{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}
代码语言:javascript
复制
package com.jimoer.jdkmoduleOne;

public class ExampleOne {


    private int id;

    private String name;

    private String arg;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getArg() {
        return arg;
    }

    public void setArg(String arg) {
        this.arg = arg;
    }

    @Override
    public String toString() {
        return "ExampleOne{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", arg='" + arg + '\'' +
                '}';
    }
}

然后在ExampleOne的module-info.java中声明导出包的路径。

代码语言:javascript
复制
module exampleOne {

     // 导出包路径
    exports com.jimoer.jdkmoduleOne.test;

}

在ExampleTwo中声明requires为引入包

代码语言:javascript
复制
module exampleTwo {
    requires exampleOne;
}

然后在ExampleTwo中使用ExampleOne中的类

代码语言:javascript
复制
ublic class ExampleTwo {

    public static void main(String[] args) {

        ExampleFirst first = new ExampleFirst();

        first.setId(1);
        first.setName("余欢水");
        first.setSex("男");
        
        System.out.println(first);
    }
}

运行结果:

代码语言:javascript
复制
ExampleFirst{id=1, name='余欢水', sex='男'}

但是当在ExampleTwo中引用ExampleOne中非导出包下的类时就会编译出错。

如上图提示,所有不被导出的包默认都被封装在模块里面。

模块的兼容性

为了使可配置的封装隔离机制能够兼容传统的类路径查找机制,JDK9提出了与“类路径”(ClassPath)相对应的“模块路径”(ModulePath)的概念。只要放在类路径上的JAR文件,都会被当作传统的JAR包来对待;相应地,只要放在模块路径上的JAR文件,即使没有使用JMOD后缀,甚至不包含module-info.class文件,也仍然会被当作一个模块来对待。

为了保证Java应用升级到JDK9之后依然使用传统的类路径,不会受到影响,制定了三条规则来保证兼容性。

  • JAR文件在类路径的访问规则:所有类路径下的JAR文件及其他资源文件,都被视为自动打包在一个匿名模块(Unnamed Module)里,这个匿名模块几乎是没有任何隔离的,它可以看到和使用类路径上所有的包、JDK模块中所有的导出包,以及模块路径是哪个所有模块中导出的包。
  • 模块在模块路径的访问规则:模块路径下的具名模块(Named Module)只能访问到她依赖定义中列明依赖的模块和包,匿名模块里所有的内容对具名模块来说都是不可见的,即具名模块看不见传统JAR包的内容。
  • JAR文件在模块路径的访问规则:如果把一个传统的、不包含模块定义的JAR文件放置到模块路径中,它就会变成一个自动模块(Automatic Module)。

模块化下的类加载器

JDK9为了保证兼容性,依然保持了三层类加载器架构以及双亲委派模型。但是为了模块化系统的顺利实施,还是对类加载器做了一些改动。

  • 首先,扩展类加载器(Extension Class Loader)被平台类加载器(Platform Class Loader)取代。因为模块化天然的支持扩展,自然不需要在存在扩展类加载器了。
  • 其次,平台类加载器和应用类加载器都不再派生自java.net.URLClassLoader,如果有程序直接依赖了这种继承关系,或者依赖了URLClassLoader类特定方法,那代码很可能会在JDK9及更高版本的JDK中崩溃。
  • 最后,JDK9中虽然仍然维持着三层类加载器和双亲委派架构,但类加载的委派关系也发生了变动。当平台及应用程序类加载器收到类加载请求,在委派给父加载器加载前,要先判断该类是否能够归属到某一个系统模块中,如果可以找到这样的归属关系,就要优先委派给负责哪个模块的加载器完成加载,这可以算是对双亲委派的第四次破坏。 JDK9前后三层类加载器的架构图对比如下:
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-07-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 模块化系统
      • 举例说明:
      • 模块的兼容性
    • 模块化下的类加载器
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档