Executing jar / class file in memory

I have a jar file (say app.jar) in a specific location, accessible as a file / stream from an http server. The problem is that app.jar itself is a frequently updated jar file that is regularly updated on the server. I have another jar file (say load.jar) that just loads by any user. At run time, the user runs load.jar, which is required to load app.jar into a separate process, storing app.jar in memory (without caching to disk), then execute app.jar and terminate itself (loading. Jar). Can this be done? Any help is much appreciated. Thanks in advance. Regards, KT

--------------------------- Update.

Hi,

Thanks to everyone for the answer. However, I think I did not give the full picture. Attached Image Link Text . 4 jars (actual common performers) are hosted on a central server. They are updated frequently (probably 3-4 times a day initially to once a day in the end). The local server in one of the elements is located, which is initialized. The launcher on the local server downloads all 4 binary files and stores them in memory - without caching to disk. These jar files are self-contained and do not depend on any library on the "Local Server" - they actually call banks from the "Local Server". The "client" console is ultimately hosted on the "local server" and sent to clients on request through the webapp using the "Local server". In addition, Launcher should exit by calling the loaded main jar from the server in a separate JVM.

Regards, KT

+4
source share
4 answers

OK Before I put the link to the szegedi article in my previous answer (honest), I prototyped a jar-launcher that could handle URLs. As the author said, it was not difficult, perhaps not complete. Attached below. I think this is 1/3 of what you need. Your user says (something like):

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

load.jar has two roles: (1) call JarLauncher (below) as the main class (2), serve app.jar on the local host (before calling JarLauncher). load.jar therefore reads its arguments to figure out which application to run.

Finally (hard bit): you have to make URLClassLoader not get to the temporary disk. As stated in the article in the shoggy, this is not easy. Alternatively, you can write your own network class loader that does not cache the disk, for example, my first suggestion is to load the URL into memory as a byte stream from the URL connection, decode it as a JarInputStream and satisfy the loadClass / findResource calls from this stream to memory.

You have a lot of work ahead. Good luck.

Apologizes for the size of the license text, but allows you to do what you like with the code, unless you blame me (BSD).

-. Simon


 / *
  * One-JAR (TM) (http://www.simontuffs.com/one-jar).  Copyright (c) 2004-2010, 
  * P. Simon Tuffs ( simon@simontuffs.com ).  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  *
  * Redistributions of source code must retain the above copyright notice, this
  * list of conditions and the following disclaimer.
  *
  * Redistributions in binary form must reproduce the above copyright notice,
  * this list of conditions and the following disclaimer in the documentation
  * and / or other materials provided with the distribution.  
  *
  * Neither the name of P. Simon Tuffs, nor the names of any contributors, 
  * nor the name One-JAR may be used to endorse or promote products derived 
  * from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  * SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE, DATA, OR PROFITS;  OR BUSINESS
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
  * Including this file inside the built One-JAR file conforms with these terms.
  * /

 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;

 / **
  * Programmatic equivalent of what happens when you say "java -jar <jar-file.jar>".
  * A better solution to debugging / running Jar files inside an IDE.
  * @author simon
  *
  * /
 public class JarLauncher {

     public static URL getURL (String string) throws 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 <jar-file.jar>");
             System.exit (1);
         }
         String jar = args [0];
         args = Arrays.copyOfRange (args, 1, args.length);
         List <URL> urls = new ArrayList <URL> ();
         // Main jar on the URL path.
         // Dig out the main class.
         urls.add (getURL (jar));
         URL jarurl = urls.get (0);
         JarInputStream jis = new JarInputStream (jarurl.openStream ());
         String main = jis.getManifest (). GetMainAttributes (). GetValue ("Main-Class");
         // OK to split on space, because embedded space is% 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 (loader);
         Method m = cls.getMethod ("main", new Class [] {new String [0] .getClass ()});
         m.invoke (null, new Object [] {args});

     }

 }

+3
source

I suggest taking a look at http://jcloader.sourceforge.net/

This improves flexibility and has rich functionality.

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"); 
+2
source

Further editing:

I browsed the web and came across this wonderful article, which may also affect your question: http://www.szegedi.org/articles/remotejars.html

In this case, most of what I wrote below does not matter, but I still leave it just in case.

Edit:

Well, I think I better understand your requirements. However, the requirements are complex, so let me tell you what I think you are trying to do, and then I will see what solutions you offer. I'm probably wrong, then we do it again.

Requirements:

Distributed caching mechanism for serving WebStart applications. Applications (.jars) are changed on a regular basis. They are self-sufficient. You want the local cache to be able to serve jar Webstart files received from the central server, storing them in memory. I do not understand your requirements for Exit.

Solutions?

What you are probably looking for is a web server that can host a webapp that will read updated application banks into memory and then serve them in the webstart launchpad. You will need to use a web server such as Jetty / Tomcat and write a simple webapp to run under it. Webapp will test the central server for application updates and make application banks accessible for webstart through the URLs it serves. Polling a central server probably makes more sense than a central server, which runs new applications on local servers for firewall and scalability reasons.

I do not know any ready-made webapps that do this, maybe one.

But, as I said, I probably still do not understand. Requirements: loved them.


I am going to make some assumptions in this answer based on your question. It looks like you want to cache "app.jar" from the remote machine throughout the life of "load.jar" on the local computer to allow isolating "load.jar" from changes to "app.jar" "during its lifetime. This seems like a good idea: I would expect that if you use URLClassLoader to cast "app.jar" into the space "load.jar", then an update in the middle of execution can lead to chaos.

It also sounds like you don’t want “load.jar” to make a copy of “app.jar” on disk - I think this is a reasonable goal: who wants old jar files to be scattered around on the machine? who wants to solve the problems associated with trying to write temporary files?

Given these goals, you need to find or implement a class loader that takes a snapshot of "app.jar" when "load.jar" first gets into the class inside it. It's not complicated: I had to do something similar in my One-JAR JarClassLoader, which loads Jar files from Jar files. During startup, it loads all found bytes into memory, and then resolves classes on demand using this storage. Although it is less efficient than lazy loading, it works quickly and stably and solves your problem.

Unfortunately, One-JAR does not allow you to cache network resources (or files) in this way. It uses delegation through a regular URL class loader, which makes it not caching your remote resources.

I suggest you take a look at the CVS repository: http://one-jar.cvs.sourceforge.net/viewvc/one-jar/one-jar/src/com/simontuffs/onejar/JarClassLoader.java?revision=1.58&view=markup

around line 678. Do not worry about the size of this class, its bunch of special cases for handling, as well as special cases.

If I had to create something from scratch, I would subclass URLClassLoader, redefine loadClass, getResource and findResource methods (see, for example, line 281, where One-JAR does this for its own requirements for inverting the loader class), insert byte caching by loading the entire "app.jar" into memory as a hashmap of a byte array indexed with class / resource keys (this is again a single-JAR), and then you will be cached in memory.

Hope this helps.

-. Simon

+2
source

You have not looked at the URLClassloader class yet?

JarClassloader may be useful here: http://www.java.happycodings.com/Other/code27.html

0
source

Source: https://habr.com/ru/post/1316013/


All Articles