网络上很多OSGi的文章上来就Activator实例,看得云里雾里。要想了解OSGi,首先要知道为什么要用
OSGi?它有哪些好处?
首先要明确:Java缺少对高级模块化的支持。OSGi服务平台是专门针对Java对模块化支持不足的情况,
由OSGi联盟定义的一个行业标准,它引入了一个面向服务的编程模型,被称作“VM中的SOA”
Java模块化的不足
为什么说Java缺少对高级模块化的支持?Java确实以面向对象的方式提供了某种程度的模块化,但它从未
考虑支持粗粒度的模块化编程。主要包括三个方面:
1. 可见性问题 / 信息隐藏
- There is no mechanism for information hiding between JARs——JAR文件直接无法实现信息隐藏。
一个Java类,可以是public,也可以是package-private;但是一个Java包呢?Java提供了很多控制可见性的
访问修饰符,但这都是为了解决低层面向对象封装,而不是解决逻辑系统划分。这就导致一个问题:如果类
要在多个包之间可见,那么就必须是public!
如果没有OSGi,就不得不采用下面这种workaround:
-
为了避免暴露非公有API,而把不相干的类放到同一个包中——损害程序的逻辑结构
而如果保持程序逻辑结构而使用多个包,则又暴露了原本不想暴露的非公有API。
2. 易错的classpath
- There is no runtime concept that corresponds to a JAR; they are only meaningful at build-time
- and deploy-time. Once the Java Virtual Ma-chine is running, the contents of all the JARs are simply
- concatenated and treated as a single, global list: the so-called “Classpath”. This model scales very
- poorly.
- They contain no standard metadata to indicate their dependencies.
- They are not versioned, and multiple versions of JARs cannot be loaded simultaneous.
因为classpath隐藏了代码版本、依赖、一致性等特性,所以容易出错!
例如,同一个项目的不同组件,依赖log4j的不同版本;则类路径可能会强制选择某个可能并不合适的版本,
会找到一个并不匹配的Jar,抛出NoSuchMethodError。
——是否可以通过Maven解决?
Class Loading and the Global Classpath
Java的类加载模型如下:
ClassLoader有两个职责:
- Finding classes, i.e. the physical bytes on disk, given their logical class——如何找类,可扩展
- Transforming those physical bytes into a Class object in memory.——通过ClassLoader.defineClass
- ()实现,这个方法是native final的,不可扩展
这种模型确保了类总是会尽可能被最上层的类加载器加载。
例如我们编写的类会被Application ClassLoader加载,该类加载器按顺序查找classpath中的实体,返回第一
个匹配实体。如果classpath中找不到,则报错ClassNotFoundException.
【总结】JRE的类加载机制是:类加载器只是简单地在classpath中按顺序查找类,并返回第一个匹配类;
JRE看到的不是一个个JAR文件,而是一个class文件列表。
Conflicting Classes
Lack of Explicit Dependencies
大部分Jar都需要依赖其他Jar,但是我们如何知道这种依赖关系?
- 靠文档描述。——不靠谱
- 靠MANIFEST.MF/Class-Path描述。——不实用,it only allows one to list further JAR files to be added
- to the classpath using absolute file-system paths, or paths relative to the file-system location
Lack of Version Information
we need to specify a version range because depending on a single specific version of a library would make our system brittle.
考虑这么一个场景:A.jar依赖于Log4j-1.1.jar,B.jar依赖于Log4j-1.2.jar,而Log4j其他版本都会有问题。
我们要把这两个Log4j版本都加到classpath中,但是JRE总是只能取到第一个jar;这样我们要么修改A.jar,要么修改B.jar
classpath=Log4j-1.2.jar; Log4j-1.1.jar
;后一个jar(Log4j-1.1.jar)中3. 部署和管理支持上的不足
在Java中存在对多个版本的依赖时,没有简单的办法来正确部署这些代码并执行;
部署之后也不易更新组件;
例如如果要支持动态插件机制,就需要动用类加载器(?)。
总结:JARs Are Not Modules
模块应该具有如下三个特性:
- Self-Contained. A module is a logical whole: it can be moved around, installed and uninstalled as a
- single unit. It is not an atom — it consists of smaller parts — but those parts cannot stand alone, and
- the module may cease to function if any single part is removed.
- Highly Cohesive. Cohesion is a measure of how strongly related or focussed the responsibilities of
- a module are. A module should not do many unrelated things, but stick to one logical purpose and
- fulfil that purpose well.
- Loosely Coupled. A module should not be concerned with the internal im-plementation of other modules that it interacts with. Loose coupling allows us to change the implementation of one module without needing to update all other modules that use it (along with any modules that use those modules, and so on).
J2EE解决方案
J2EE应用服务器都具有deployment system,允许动态地部署、解部署应用,而无需重启服务器、不会影响其他应用。
这意味着标准Java应用所使用的类加载机制是不够用的;因为扁平化的全局classpath会导致一个应用中的类,会很容易影响到其他应用。所以J2EE使用了一个更复杂的类加载机制:
- 如果某个类需要在EJB和WAR中共享,则其必须由EAR类加载器加载;
- 如果某个类需要在EAR之间共享,则需要由Application类加载器加载;
但是这种类就不能动态部署了,并且所有EAR都会依赖这个类,而不管是否需要。
为了达到动态部署的目的,一般的做法是在每个EAR中分别重复部署该类。
OSGi解决方案
每个模块都有自己独立的classpath
OSGi类加载机制
- OSGi为每个bundle提供一个类加载器,该加载器能够看到bundle Jar文件内部的类和资源;
- 为了让bundle能互相协作,可以基于依赖关系,从一个bundle类加载器委托到另一个bundle类加载器。
优点
- 找不到类时的错误提示更友好。假如bundleE不存在,则bundleC就不会被解析成功,会有错误消息提示为何未能解析;而不是报错ClassNotFoundException或NoClassDefFoundError。
- 效率更高。在标准Java类加载模型中,总是会在classpath那一长串列表中进行查找;而OSGi类加载器能立即知道去哪里找类。
解决模块化问题
- OSGi可以帮助你先确保代码满足依赖关系,然后才允许执行代码;避免类路径错误
- OSGi会对类路径上的依赖集进行一致性检查(如:版本);
- 不必担心由于层次化的类加载模式隐含的限制;——何种限制?
- OSGi可以把程序打包逻辑上独立的JAR文件,并且只部署指定的部分、动态部署;——OSGi生命周期层实现动态部署
- OSGi可以声明JAR中的哪些代码可以被其他JAR访问,强化可见性; ——OSGi中,只有那些被显式导出的包才能被其他bundle使用。也就是说默认情况下,所有包都是bundle private的,不能被其他包看到。
- OSGi为程序定义了一个插件式的扩展机制。
相关推荐
### OSGi——Java模块化框架的实现与进化 #### OSGi概述 ...随着时间的推移和技术的进步,未来可能会出现更多简化模块化框架的方法,但OSGi作为当前最成熟的Java模块化解决方案之一,仍然值得深入学习和研究。
OSGi 是 Java 的一个运行时动态模块系统,提供了静态模块化和动态模块化的解决方案。OSGi 规范描述了 OSGi 运行时的工作行为方式。 在 Java 开发中,模块化技术栈包括: * OSGi * Maven * Java 9 的模块化系统 ...
Java9的模块化系统,也称为JPMS,旨在解决Java应用程序的复杂性和依赖性管理问题。它通过定义清晰的模块边界,使得代码组织更加有序,提高了可读性和可维护性。JPMS的核心概念包括模块(Module)、模块声明(Module ...
java.Java9的模块化(解决方案).md
java.模块化系统(解决方案).md
### Android模块化编译速度解决方案 #### 概述 在Android开发过程中,随着应用功能的增加,项目的规模逐渐增大,导致编译时间显著延长。为了提高开发效率、降低编译时间,采用模块化的开发方式是一种有效的方法。...
**TITAN:Java模块化开发框架详解** TITAN是一个专为Java开发者设计的模块化开发框架,其核心目标是提升开发效率、优化代码结构并实现应用的高可扩展性。通过TITAN,开发者可以轻松地在运行时动态加载、卸载模块,...
Java报表解决方案是针对企业信息化系统中的数据展示需求而设计的一种技术方案,特别是在中国的环境中,由于业务规则复杂,报表往往需要具备强大的数据处理、格式化和展示能力,这被称为“中国式复杂报表”。...
3. **模块化系统(Jigsaw)**:Java 9引入了模块系统,通过`module-info.java`文件来声明和管理模块及其依赖,对类路径有了更细粒度的控制。 总结,Java路径问题的解决方案涉及类路径设置、自定义类加载器以及利用...
在IT行业中,构建多模块项目是一项常见的任务,尤其在大型软件开发中,为了更好地管理和组织代码,采用模块化的架构设计是必要的。本文将详细介绍如何创建一个适用于多模块项目的解决方案,以便于团队协作和代码维护...
JarsLink是一个由阿里巴巴开源的Java模块化开发框架,旨在解决大型项目中常见的模块划分与管理问题。它提供了运行时动态加载、卸载模块以及模块间通信的API,允许开发者进行模块化的系统构建,提高开发效率,降低...
MTK(MediaTek)是一家知名的半导体公司,主要为移动设备提供芯片解决方案。在智能手机和平板电脑领域,MTK的Java模块是其操作系统中的一个重要组成部分,它负责处理Java应用程序的运行环境。这个PPT将深入探讨MTK ...
基于Java的模块化远程监测分析系统设计与实现 Java作为一种基于对象的编程语言,具有良好的跨平台、多线程、稳定安全和高性能等特点,已经成为主流的网络语言。 在基于Java的模块化远程监测分析系统设计与实现中,...
这使得Java编写的代码更加模块化、可维护和可扩展。 多线程支持: Java内置了对多线程的支持,允许程序同时执行多个任务。这对于开发需要高并发性能的应用程序(如服务器端应用、网络应用等)非常重要。 自动内存...
这个脚手架的子文件名“前端java模块化”可能包含了关于如何在前端应用中实现类似Java的模块化、面向对象编程的示例代码、配置文件或文档。开发者可以学习和参考这些文件,以更好地理解和使用这个工具,提升前端开发...
3. **Hibernate**:Hibernate是一个持久化框架,它简化了Java对象与数据库之间的映射关系,提供了一种ORM(Object-Relational Mapping)解决方案,使得开发者可以使用面向对象的方式来操作数据库。 **Maven与SSH...
综上所述,实现“JAVA实现万能打印模块”是一个涉及Java PrintService API、Graphics2D绘图、用户界面设计以及模块化编程等多个技术领域的项目。通过细致的设计和实现,我们可以构建出一个强大而灵活的打印解决方案...
该开源云计算解决方案项目名为“基于Java语言的CloudStack”,包含8416个文件,涵盖多种编程语言,其中Java文件最多,达5766个。项目文件类型丰富,包括525个XML配置文件、226个Shell脚本、211个Vue模板、183个...