知识大全 用 One-JAR 简化应用程序交付

Posted 文件

篇首语:没有知识就不可能对生活作出正确的解释。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 用 One-JAR 简化应用程序交付相关的知识,希望对你有一定的参考价值。

用 One-JAR 简化应用程序交付  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  如果您曾经试图把 Java 应用程序交付为单一的 Java 档案文件(JAR 文件) 那么您很有可能遇到过这样的需求 在构建最终档案文件之前 要展开支持 JAR 文件(supporting JAR file) 这不但是一个开发的难点 还有可能让您违反许可协议 在本文中 Tuffs 向您介绍了 One JAR 这个工具 它使用定制的类装入器 动态地从可执行 JAR 文件内部的 JAR 文件中装入类   有人曾经说过 历史总是在不断地重复自身 首先是悲剧 然后是闹剧 最近 我第一次对此有了亲身体会 我不得不向客户交付一个可以运行的 Java 应用程序 但是我已经交付了许多次 它总是充满了复杂性 在搜集应用程序的所有 JAR 文件 为 DOS 和 Unix(以及 Cygwin)编写启动脚本 确保客户端环境变量都指向正确位置的时候 总是有许多容易出错的地方 如果每件事都能做好 那么应用程序能够按它预期的方式运行 但是在出现麻烦时(而这又是常见的情况) 结果就是大量时间耗费在客户端支持上     最近与一个被大量 ClassNotFound 异常弄得晕头转向的客户交谈之后 我决定自己再也不能忍受下去了 所以 我转而寻找一个方法 可以把我的应用程序打包到单一 JAR 文件中 给我的客户提供一个简单的机制(比如 java jar)来运行程序     努力的结果就是 One JAR 一个非常简单的软件打包解决方案 它利用 Java 的定制类装入器 动态地从单一档案文件中装入应用程序所有的类 同时保留支持 JAR 文件的结构 在本文中 我将介绍我开发 One JAR 的过程 然后告诉您如何利用它在一个自包含的文件中交付您自己的可以运行的应用程序      One JAR 概述  在介绍 One JAR 的细节之前 请让我首先讨论一下我构建它的目的 我确定一个 One JAR 档案文件应该是     可以用 java jar 机制执行     能够包含应用程序需要的 所有 文件 —— 也就是说 包括原始形式(未展开)的类和资源     拥有简单的内部结构 仅仅用 jar 工具就可以被装配起来     对原来的应用程序不可见 —— 也就是说 无需修改原来的应用程序 就可以把它打包在 One JAR 档案文件内部      问题和解决方案  在开发 One JAR 的过程中 我解决的最大问题 就是如何装入包含在另外一个 JAR 文件中的 JAR 文件 Java 类装入器 sun misc Launcher$AppClassLoader(在 java jar 开始的时候出现)只知道如何做两件事     装入在 JAR 文件的根出现的类和资源     装入 META INF/MANIFEST MF 中的 Class Path 属性指向的代码基中的类和资源   而且 它还故意忽略针对 CLASSPATH 的全部环境变量设置 还忽略您提供的命令行参数 cp 所以它不知道如何从一个包含在其他 JAR 文件中的 JAR 文件装入类或资源     显然 我需要克服这个问题 才能实现 One JAR 的目标     解决方案 展开支持 JAR 文件  我为了创建单一可执行 JAR 文件所做的第一个尝试 显然就是在可交付的 JAR 文件内展开支持 JAR 文件 我们把可交付的文件称为 main jar 假设有一个应用程序的类叫做 main Main 而且它依赖两个类 —— a A (在 a jar 中) 和 b B(在 b jar 中) 那么 One JAR 文件看起来应该像这样     main jar  | /main/Main class  | /a/A class  | /b/B class    这样 最初来源于 a jar 文件的 A class 丢失了 B class 也是如此 虽然这看起来只是个小问题 但却会真正带来问题 我很快就会解释为什么      One JAR 和 FJEP  最近发布的一个叫做 FJEP (FatJar Eclipse Plugin) 的工具支持在 Eclipse 内部直接构建扁平 JAR 文件 One JAR 已经与 FatJar 集成在一起 以支持在不展开 JAR 文件的情况下嵌入 JAR 文件 请参阅 参考资料 了解有关详细内容     把 JAR 文件展开到文件系统以创建一个扁平结构 这可能非常耗时 还需要使用 Ant 这样的构建工具来展开和重新归档支持类     除了这个小麻烦之外 我很快又遇到了两个与展开支持 JAR 文件有关的严重问题     如果 a jar 和 b jar 包含的资源的路径名相同 (比如说 都是 log j properties ) 那么您该选哪个?    如果 b jar 的许可明确要求您在重新发布它的时候不能修改它 那您怎么办?您无法在不破坏许可条款的前提下像这样展开它   我觉得这些限制为另外一种方法提供了线索      解决方案 : MANIFEST Class Path  我决定研究 java jar 装入器中的另外一种机制 装入的类是在档案文件中一个叫做 META INF/MANIFEST MF 的特殊文件中指定的 通过指定称为 Class Path 的属性 我希望能够向启动时的类装入器添加其他档案文件 下面就是这样的一个 One JAR 文件看起来的样子     main jar  | META INF/MANIFEST MF  | + Class Path: lib/a jar lib/b jar  | /main/Main class  | lib/a jar  | lib/b jar     说明与线索  URLClassloader 是 sun misc Launcher$AppClassLoader 的基类 它支持一个相当神秘的 URL 语法 让您能够引用 JAR 文件内部的资源 这个语法用起来像这样 jar:file:/fullpath/main jar!/a resource     从理论上讲 要获得一个在 JAR 文件 内部 的 JAR 文件中的项 您必须使用像 jar:file:/fullpath/main jar!/lib/a jar!/a resource 这样的方式 但是很不幸 这么做没有用 JAR 文件协议处理器在找 JAR 文件时 只认识最后一个 !/ 分隔符     但是 这个语法确实为我最终的 One JAR 解决方案提供了线索……    这能工作么? 当我把 main jar 移动到另外一个地方 并试着运行它时 好像是可以了 为了装配 main jar 我创建了一个名为 lib 的子目录 并把 a jar 和 b jar 放在里面 不幸的是 应用程序的类装入器只从文件系统提取支持 JAR 文件 而不能从嵌入的 JAR 文件中装入类     为了克服这一问题 我试着用神秘的 jar:!/ 语法的几种变体来使用 Class Path(请参阅 说明和线索 ) 但是没有一次成功 我能 做的 就只有分别交付 a jar 和 b jar 并把它们与 main jar 一起放在文件系统中了 但是这正是我想避免的那类事情      进入 JarClassLoader  此时 我感到备受挫折 我如何才能让应用程序从它自己的 JAR 文件中的 lib 目录装入它自己的类呢?我决定应当创建定制类装入器来承担这个重任 编写定制类装入器不是一件容易的事情 但是实际上这个工作并没有那么复杂 类装入器对它所控制的应用程序有非常深刻的影响 所以在发生故障的时候 很难诊断和解释故障 虽然对于类装入的完整处理超出了本文的范围(请参阅 参考资料) 我还是要介绍一些基本概念 好保证您能从后面的讨论中得到最大收获      装入类  当 JVM 遇到一个对象的类未知的时候 就会调用类装入器 类装入器的工作是找到类的字节码(基于类的名称) 然后把这些字节传递给 JVM JVM 再把这些字节码链接到系统的其余部分 使得正在运行的代码可以使用新装入的类 JDK 中关键的类是 java lang Classloader 以及 loadClass 方法 摘要如下     public abstract class ClassLoader      protected synchronized Class loadClass(String name boolean resolve)  throws ClassNotFoundException       ClassLoader 类的主要入口点是 loadClass() 方法 您会注意到 ClassLoader 是一个抽象类 但是它没有声明任何抽象方法 这样 关于 loadClass() 方法是不是要关注的方法 一点线索也没留下 实际上 它不是 要关注的主方法 回到过去的好时光 看看 JDK 的类装入器 可以看到 loadClass() 是您可以有效扩展类装入器的惟一地方 但是从 JDK 起 最好让类装入器单独做它所做的工作 即以下工作     检查类是否已经装入   检查上级类装入器能否装入类   调用 findClass(String name) 方法 让派生的类装入器装入类   ClassLoader findClass() 的实现是抛出一个新的 ClassNotFoundException 异常 并且是我们实现定制类装入器时要考虑的第一个方法     JAR 文件何时不是 JAR 文件?  为了能够装入在 JAR 文件内部 的 JAR 文件中的类(这是关键问题 您可以回想起来) 我首先必须能够打开并读取顶层的 JAR 文件(上面的 main jar 文件) 现在 因为我使用的是 java jar 机制 所以 java class path 系统属性中的第一个(也是惟一一个)元素是 One JAR 文件的完整路径名!用下面的代码您可以得到它     jarName = System getProperty( java class path );    我接下来的一步是遍历应用程序的所有 JAR 文件项 并把它们装入内存 如清单 所示     清单 遍历查找嵌入的 JAR 文件    JarFile jarFile = new JarFile(jarName);  Enumeration enum = jarFile entries();  while (enum hasMoreElements())   JarEntry entry = (JarEntry)enum nextElement();  if (entry isDirectory()) continue;  String jar = entry getName();  if (jar startsWith(LIB_PREFIX) || jar startsWith(MAIN_PREFIX))   // Load it!  InputStream is = jarFile getInputStream(entry);  if (is == null)  throw new IOException( Unable to load resource / + jar + using + this);  loadByteCode cha138/Article/program/Java/JSP/201311/19228

相关参考

电力工程应用软件中造型简化的原则?

1可采用不影响对图理解的任何简化方法。  2含义应明确,不会因简化而导致与其他造型(特别同类造型或相近造型)相混淆。  3造型的轮廓应简单清晰,其尺寸应与所表示实体一致或能包容所表示实体。  4连接部

知识大全 在Fedora Core上交付Java应用

在FedoraCore上交付Java应用  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在Fed

知识大全 类反射简化Struts应用程序的开发(二)

类反射简化Struts应用程序的开发(二)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  三如何

知识大全 类反射简化Struts应用程序的开发(一)

类反射简化Struts应用程序的开发(一)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一St

知识大全 简化基于数据库的DotNet应用程序开发

简化基于数据库的DotNet应用程序开发  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  分析  

应用谷子简化栽培技术需要注意哪些事项?

(1)播前准备。每公顷土地施农家肥30000千克左右,或氮磷钾复合肥225~300千克,浇地后或雨后播种,保证墒情适宜。  (2)播种量与播种方式。在黄淮海地区平原春白地或在麦茬播种地块播种量13.5

应用谷子简化栽培技术需要注意哪些事项?

(1)播前准备。每公顷土地施农家肥30000千克左右,或氮磷钾复合肥225~300千克,浇地后或雨后播种,保证墒情适宜。  (2)播种量与播种方式。在黄淮海地区平原春白地或在麦茬播种地块播种量13.5

知识大全 linux下的应用开发起步--简化蚂蚁制作(三)

   C前面看了一大段是不是有点云里雾里的啊?是有点罗嗦但是俗话说万事总是开头难OK现在总算可以写主程序文件了      下面就是antc文件    #includeanth  #includesig

应用谷子简化栽培技术是不是成本很高?

不是很高。目前,这项技术需要使用两种除草剂,一种是播种后出苗前封地使用的除草剂,叫做谷友,成本105元/公顷左右,用于防治双子叶杂草,抑制单子叶杂草;另一种叫壮谷灵,在3~5叶期茎叶喷施,用于防治单子

应用谷子简化栽培技术是不是成本很高?

不是很高。目前,这项技术需要使用两种除草剂,一种是播种后出苗前封地使用的除草剂,叫做谷友,成本105元/公顷左右,用于防治双子叶杂草,抑制单子叶杂草;另一种叫壮谷灵,在3~5叶期茎叶喷施,用于防治单子