• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Ron McLeod
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

Standalone jar class/resource loading

 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi folks,

I just posted a quick question about jarEntry loading. I'm trying to put together a JarClassloader that allows you to run an application completely from within a jar app. It is basically an extension of Simon tuffs excellent one-jar application that can be located here.

http://one-jar.sourceforge.net/

Without this application I'd never have gotten close to figure out how to use the JAR API never mind attempt to put something like this together.

I'm getting to the stage where I have to decide on a pattern for loading internal jar files and their resources. I'm not too familiar with patterns so I was hoping maybe we could bandy about a few ideas as to what would be the proper, safest, fastest way to load classes and their resources.

The following archive structure gives a brief example of what I'm trying to achieve


[edit] sorry the indentation of the jar structure was removed and I only noticed a couple of hours later.


So basically from the structure, ClassA requires ClassB and ClassB requires classC and so on.

The current JarClassLoader implemented parses the manifest of jarA.jar. One jar that is an entry of another jar e.g. jarB.jar in jarA.jar
will only be loaded if it is declared in the Manifest of the containing archive. Otherwise it is skipped and a warning is thrown.

It catalogs and loads any classes/resources that it finds in the initial jar, jarA.jar. Any internal jars it comes across, i.e. libs/jarB.jar it also catalogs and loads any classes within. Within the process of cataloging jarB.jar if it encounters a further inner jar i.e. jarC.jar, it
extracts it to the file system to a temp dir and catalogs it. I understand that this extraction is not perfect but try as I may I
couldn't get an inputstream to 2nd level embedded jar without extracting it.

The difference between cataloging and loading is simply that cataloging a resource simply records in memory where the resource can be found.
Loading involves retrieving the actual bytes into memory. As of today I've decided to simply load the resources in the root of the initial jar
i.e. jarA.jar and solely catalogue the resources for a further two levels of archiving, and from this employ lazy loading for any class/resource files
that don't reside as entries of the initial jar.

i.e. load classes/resources from jarA.jar but only catalog resources from jars B & C.

By cataloging, a treemap is created mapping packages and resources to locations.
By loading, a resourceByteCode repository is created with byte arrays and codesources associated with loaded resources.

Loading classes
=================
When a class is requested, the classLoader queries the resourceByteCode repository and if it's already loaded then it returns the bytes.
If not loaded it checks the tree map to see if it has been catalogued. If so the location is retrieved from the tree and the class is
loaded from the archive where it was first encountered in the cataloging. i.e. if ClassA appeared in both jarA and jarB , the version
located in jarA would be loaded.

Loading resources such as Property files
========================================
In terms of resources such as property files or basically anything retrieved using Thread.currentThread.getContextClassLoader().getResource() method,
currently if the resource appears on the classpath of the java command i.e. java -classpath then it is loaded from there first. I understand this is not
what is meant by standalone jar but a developer may wish to override resource files without recreating the jar.
If the resource doesn't exist on the classpath then the stacktrace to the method call is descended until we arrive at the class where the resource was requested. The resource location for this class is retrieved and the resource is only searched for within this archive.
For example, ClassB uses log4j. A request from this class for the resource config.log4j.properties is successful as the props file is
located in the same archive.
If however, ClassC was to attempt to load config.log4j.properties then it will fail as it seems more appropriate that much in the same way that
superclasses should never know about their subclasses attributes, in a situation where Application B is built using Application C, App C should have
no reason to be aware of any of the resources App B.

** The resource loading section described here is still being worked on.

What is in the pipeline (I think) is a tiering of Classloaders that maintain the various levels of archive indentation i.e. the classes/resources in jars
C and D in the above example would be loaded by one classloader, the classes/resources of jarB by another and those of jarA by yet another.
The hierarchy would be parent/child starting from root jar as the sole parent. The class loading delegation model would be parent first but the
classpath of the java command will always be searched first before resorting to the JarLoading hierarchy. (this could be switched to JarLoading first
or even to a caller delegation model as described in the resource section)

Well that's the height of it at the minute. I'd love a few comments as to the loading model that should be employed
as this description has been fairly hamfisted together while my boss is out of the room ;-) If folks think it's a useless
application then I'd fully appreciate that too just please give a reason or so. A wise man on the JBoss mailing list said
there are no negative comments.

Thanks,
Mark

[ November 29, 2005: Message edited by: Mark Gargin ]

[ November 29, 2005: Message edited by: Mark Gargin ]
[ November 29, 2005: Message edited by: Mark Gargin ]
 
reply
    Bookmark Topic Watch Topic
  • New Topic