在内存jar /类文件中执行

我在某个位置有一个jar文件(例如app.jar),可以作为来自http服务器的文件/流。 问题是app.jar本身是一个经常更新的jar文件,在服务器上定期更新。 我有另一个jar文件(比如load.jar),任何用户都可以下载。 在运行时,用户运行load.jar,这需要在单独的进程中加载​​app.jar,将app.jar保存在内存中(不缓存到磁盘),然后执行app.jar并终止自身(加载。jar)。 有可能吗? 任何帮助都非常感谢。 提前致谢。 此致,KT

—————————更新。

嗨,

谢谢大家的回复。 但是,我想我还没有给出完整的图片。 附上描绘场景的图像链接文本 。 4个jar子(实际的通用执行器)托管在中央服务器上。 这些经常更新(最初每天最多3-4次,最终每天一次)。 托管其中一个成员的本地服务器,该服务器已初始化。 本地服务器上的启动程序会下载所有4个二进制文件并将其保留在内存中 – 不会缓存到磁盘。 这些jar文件是自给自足的,并且不依赖于“本地服务器”上的任何库 – 它们实际上是从“本地服务器”调用jar。 “客户端”jar最终由“本地服务器”托管,并通过“本地服务器”通过webapp按需转发给其客户端。 此外,Launcher需要通过在单独的JVM中从服务器调用下载的Main jar来退出。

此致,KT

好。 在我将szegedi文章的链接放入我之前的回答(诚实)之前,我制作了一个可以处理URL的jar启动器原型。 就像作者所说,这并不难,可能还不完整。 附在下面。 我认为这是你需要的1/3。 您的用户说(类似):

java -jar load.jar http:// localhost:8080 / app.jar

load.jar有两个角色:(1)调用JarLauncher(下面),因为它的主类(2)在localhost端口上提供app.jar(在调用JarLauncher之前)。 因此,load.jar读取其参数以确定要运行的应用程序。

最后(硬位):你必须让URLClassLoader没有命中临时磁盘。 正如塞格迪的文章所说,这并不容易。 或者,你可以编写自己的网络感知类加载器,它不是磁盘缓存,就像我的第一个建议将URL作为来自URL连接的字节流加载到内存中,将其解码为JarInputStream,并满足对loadClass /的调用来自内存中的流的findResource。

你有很多工作要做。 祝你好运。

对许可文本的大小表示歉意,但只要你不责备我(BSD),它就可以让你用代码做你喜欢的事。

–simon。



 / * * One-JAR(TM)(http://www.simontuffs.com/one-jar)。 版权所有(c)2004-2010,* P. Simon Tuffs(simon@simontuffs.com)。 版权所有。  * *如果满足以下条件,则允许以源代码和二进制forms重新分发和使用,无论是否经过*修改:* *源代码的重新分发必须保留上述版权声明,此*条件列表和以下免责声明。  * *二进制forms的再分发必须在文档*和/或随分发提供的其他材料中复制上述版权声明,*此条件列表和以下免责声明。  * *未经事先书面许可,不得使用P. Simon Tuffs的名称,也不得使用任何贡献者的姓名*,也不得使用One-JAR这个名称来支持或宣传本软件衍生的产品*。  * *本软件由版权所有者和贡献者按“原样”*提供,并且不承担任何明示或暗示的担保,包括但不限于*适销性和特定用途的适用性*暗示担保*。 在任何情况下,版权所有者或贡献者均不对任何直接,间接,偶然,特殊,惩戒性或间接损害承担责任(包括但不限于采购*替代商品或服务;损失使用,数据,或者利润或者业务*中断)但是引起任何责任理论,无论是*合同,严格责任,还是侵权(包括疏忽或其他)*以任何方式使用本软件,即使被告知*这种损害的可能性。  * *在构建的One-JAR文件中包含此文件符合这些条款。  * / import java.lang.reflect.Method;  import java.net.MalformedURLException;  import java.net.URL;  import java.net.URLClassLoader;  import java.util.ArrayList;  import java.util.Arrays;  import java.util.List;  import java.util.jar.JarInputStream;  / ** *当你说“java -jar ”时会发生什么的程序化等价物。  *在IDE中调试/运行Jar文件的更好解决方案。  * @author simon * * / public class JarLauncher {public static URL getURL(String string)抛出MalformedURLException {try {return new URL(string);  } catch(MalformedURLException x){return new URL(“file:”+ string);  public static void main(String args [])throws Exception {if(args.length <1){System.out.println(“Usage:java [-Dkey = value ...] JarLauncher “);  System.exit(1);  } String jar = args [0];  args = Arrays.copyOfRange(args,1,args.length);  List  urls = new ArrayList ();  // URL路径上的主jar。  //挖出主要课程。  urls.add(使用getURL(jar));  URL jarurl = urls.get(0);  JarInputStream jis = new JarInputStream(jarurl.openStream());  String main = jis.getManifest()。getMainAttributes()。getValue(“Main-Class”);  //可以拆分空间,因为嵌入空间是%20 String classpaths [] = jis.getManifest()。getMainAttributes()。getValue(“Class-Path”)。split(“”);  for(String classpath:classpaths){urls.add(getURL(classpath));  URLClassLoader loader = new URLClassLoader(urls.toArray(new URL [0]));  Class <?> cls = loader.loadClass(main);  Thread.currentThread()setContextClassLoader(装载机)。 方法m = cls.getMethod(“main”,new Class [] {new String [0] .getClass()});  m.invoke(null,new Object [] {args});  }} 

我建议看看http://jcloader.sourceforge.net/

这具有更好的灵活性,function丰富。

JarClassLoader jcl = new JarClassLoader(); //Loading classes from different sources jcl.add("myjar.jar"); jcl.add(new URL("http://myserver.com/myjar.jar")); jcl.add(new FileInputStream("myotherjar.jar")); jcl.add("myclassfolder/"); //Recursively load all jar files in the folder/sub-folder(s) jcl.add("myjarlib/"); JclObjectFactory factory = JclObjectFactory.getInstance(); //Create object of loaded class Object obj = factory.create(jcl, "mypack.MyClass"); 

进一步编辑:

我扫描了网页,发现了这篇也可能与你的问题有关的优秀文章: http : //www.szegedi.org/articles/remotejars.html

在这种情况下,我在下面写的大部分内容都是无关紧要的,但我会留下它以防万一。

编辑:

好的,我想我能更好地了解您的要求。 虽然要求很棘手,所以让我告诉你我认为你想做什么,然后我会看到有什么解决方案。 我可能会弄错,然后我们再做一次。

要求:

用于服务WebStart应用程序的分布式缓存机制。 应用程序(.jars)会定期更改。 它们是独立的。 您希望本地缓存能够提供从中央服务器获取的Webstart jar文件,并将它们保存在内存中。 我不明白你对退出的要求。

解决方案?

您可能正在寻找的是一个Web服务器,它可以托管一个webapp,将更新的应用程序jar读入内存,然后将它们提供给webstart启动器。 您将需要使用诸如Jetty / Tomcat之类的Web服务器,并编写一个简单的webapp以在其下运行。 webapp将轮询中央服务器以获取应用程序更新,并将通过它所服务的URL使应用程序jar可用于webstart。 由于防火墙和可扩展性的原因,轮询中央服务器可能比让中央服务器将新应用程序推送到本地服务器更有意义。

我不知道有任何现成的webapps这样做,可能有一个。

但就像我说的那样,我可能仍然没有得到这个。 要求:得爱他们。


根据你的问题,我将在这个答案中作出一些假设。 听起来你想在本地机器上“load.jar”的生命周期中从远程机器缓存“app.jar”,以便将“load.jar”与“app.jar”的更改隔离开来“在其一生中。 这似乎是一个好主意:我希望如果你使用URLClassLoader将“app.jar”带入“load.jar”空间,那么执行中途的更新可能会造成严重破坏。

听起来你也不想让“load.jar”制作一个基于磁盘的“app.jar”副本 – 我认为这是一个合理的目标:谁想把旧的jar文件分散在机? 谁想要与试图写临时文件有关的权限问题?

鉴于这些目标,您需要找到或实现一个类加载器,当“load.jar”首次访问其中的类时,该类加载器会生成“app.jar”的快照。 这并不难:我必须在我的One-JAR JarClassLoader中做类似的事情,它从Jar文件中加载Jar文件。 在启动期间,它将所有找到的字节加载到内存中,然后使用该内存存储按需解析类。 虽然可能比延迟加载效率低,但速度快且稳定,可以解决您的问题。

不幸的是,One-JAR不允许以这种方式缓存网络(或文件)资源。 它通过普通的URL类加载器使用委托,这样就不会缓存远程资源。

我建议你看看CVS存储库: http : //one-jar.cvs.sourceforge.net/viewvc/one-jar/one-jar/src/com/simontuffs/onejar/JarClassLoader.java?revision=1.58 &视图=标记

678行。不要被这个类的大小吓倒,它是一堆特殊情况要处理,好吧,特殊情况。

如果我必须从头开始创建一些东西,我会inheritanceURLClassLoader,覆盖loadClass,getResource和findResource方法(参见第281行,其中One-JAR为其自己的类加载器反转需要执行此操作),放入字节码缓存将整个“app.jar”加载到内存中,作为由类/资源名称键索引的字节数组哈希映射(再次是One-JAR),然后将其缓存在内存中。

我希望这有帮助。

–simon。

你有没看过URLClassloader类呢?

这里的JarClassloader可能很有用: http : //www.java.happycodings.com/Other/code27.html