I found this in the System class, but I want to know how this is implemented.
/**
* System properties. The following properties are guaranteed to be defined:
* <dl>
* <dt>java.version <dd>Java version number
* <dt>java.vendor <dd>Java vendor specific string
* <dt>java.vendor.url <dd>Java vendor URL
* <dt>java.home <dd>Java installation directory
* <dt>java.class.version <dd>Java class version number
* <dt>java.class.path <dd>Java classpath
* <dt>os.name <dd>Operating System Name
* <dt>os.arch <dd>Operating System Architecture
* <dt>os.version <dd>Operating System Version
* <dt>file.separator <dd>File separator ("/" on Unix)
* <dt>path.separator <dd>Path separator (":" on Unix)
* <dt>line.separator <dd>Line separator ("\n" on Unix)
* <dt>user.name <dd>User account name
* <dt>user.home <dd>User home directory
* <dt>user.dir <dd>User's current working directory
* </dl>
*/
private static Properties props;
private static native Properties initProperties(Properties props);
Since it is a native method, I assume there is a C-File, which does all the magic.
Is there a os-specific file which loads the variables via getenv() in C or is this hard coded somehow for specific platforms (regardless from os.name, os.version etc, which have to be dynamic)?
What if the OS is a modified Linux-Kernel with an a as line separator or <foo> as path separator? How can the JVM even know where to search for these native files, if they are stored underneath ..<foo>..<foo>native<foo>amd_xyz before even knowing the path separator?
Is there a way to look into the implementation?
You can look at all the source in the OpenJDK. Most of the source is available to your IDE from the JDK.
I think you are assuming there is more magic than there is. For the UNIX versions the file.separator is likely to be hard coded as it suggests in the documentation.
Have a look at the OpenJDK source. For example the file separator for Linux is defined like this:
inline const char* os::file_separator() {
return "/";
}
Related
When I create a new Java file in NetBeans, I get auto documentation for #author. How can I setup NetBeans that is also documents the time and date of creation of the class?
I know NetBeans can do it as I get the time and date of creation in new CSS files by default.
You can change the template files in Netbeans. Go to Tools|Templates. From the available templates, find the one you want to change, let's say Java|Java Class, then select Open in Editor
Then goto to FaqTemplateVariables for list of available template variables. In your case, you're looking for ${date} and {$time}
Then you modify the template the way want, for example...
<#assign licenseFirst = "/*">
<#assign licensePrefix = " * ">
<#assign licenseLast = " */">
<#include "${project.licensePath}">
<#if package?? && package != "">
package ${package};
</#if>
/**
*
* #author ${user}
* ${date} ${time}
*/
public class ${name} {
}
Then simple create a new "Java Class" - File|New File|Java|Class and it should then generate a file similar to this...
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package my.awesome.library;
/**
*
* #author noob
* 25/06/2017 3:19:39 PM
*/
public class Test {
}
Now, you'll probably have to go through a number of the other templates and update them, but that gives you a place to start
#MadProgrammer answered well. Just in case as an addition to this answer. U can optionally add properties in the User.properties file which is read by the various templates in the Tools -> Templated ->* configs. So if u want to add version to your Java classes. you can define the #version in the Java class template and then define the property in the User.properties file as in the following
In Your Java class template
....
/**
* ${date} ${time}
* ${version}
* ...other
*/
U can then set these properties in the User.properties file as
version=1.0.0
etc
I'm working on a monitoring application, which uses Sigar for monitoring to monitor different kind of applications. One problem with Sigar is that when monitoring the heap usage of a Java application (JVM) I only get the maximum heap size but not the actually used heap size of the JVM.
So I extended my monitoring application to use JMX to connect to a JVM and retrieve the CPU as well as the heap usage. This works fine so far, but
I want to automise everything as much as possible and I don't want to start all my applications, being monitored, with JMX activated, but activate it dynamically when needed with the following piece of code:
private void connectToJVM(final String pid) throws IOException, AgentLoadException, AgentInitializationException {
List<VirtualMachineDescriptor> vms = VirtualMachine.list();
for (VirtualMachineDescriptor desc : vms) {
if (!desc.id().equals(pid)) {
continue;
}
VirtualMachine vm;
try {
vm = VirtualMachine.attach(desc);
} catch (AttachNotSupportedException e) {
continue;
}
Properties props = vm.getAgentProperties();
String connectorAddress = props.getProperty(CONNECTOR_ADDRESS);
if (connectorAddress == null) {
String agent = vm.getSystemProperties().getProperty("java.home") + File.separator + "lib"
+ File.separator + "management-agent.jar";
vm.loadAgent(agent);
// agent is started, get the connector address
connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
}
vm.detach();
JMXServiceURL url = new JMXServiceURL(connectorAddress);
this.jmxConnector = JMXConnectorFactory.connect(url);
}
}
This works fine so far but the problem is that I have now a dependency to the tools.jar from the JDK.
My question is now can I somehow check during runtime if the tools.jar is available in the JAVA_HOME path and load it when it is? Because if it isn't available I just want to do the normal monitoring with Sigar, but if it is available I want to use JMX for monitoring Java applications.
My project is a maven project and I'm using the maven-shade-plugin to create a executable jar with all dependencies in it.
Currently I'm using a dirty hack I found in the internet which uses reflection to add the tools.jar dynamically to the system classpath if it exists. But I'm wondering if it is possible to do it differently as well?
Thanks in advance for your support.
I do a similar thing in my project, look here.
The idea is to load your utility class by differrent ClassLoader which has tools.jar in path.
File javaHome = new File(System.getProperty("java.home"));
String toolsPath = javaHome.getName().equalsIgnoreCase("jre") ? "../lib/tools.jar" : "lib/tools.jar";
URL[] urls = new URL[] {
getClass().getProtectionDomain().getCodeSource().getLocation(),
new File(javaHome, toolsPath).getCanonicalFile().toURI().toURL(),
};
URLClassLoader loader = new URLClassLoader(urls, null);
Class<?> utilityClass = loader.loadClass("some.package.MyUtilityClass");
utilityClass.getMethod("connect").invoke(null);
Finding tools.jar on the filesystem is a little more tricky than #apangin's solution.
Different JDK's stick the tools.jar in different places as shown by this method, which claims to support the IBM JDK and HotSpot on Mac.
But even the code I've referenced looks out of date. It suggests all mac JDK's use classes.jar, but my Mac 1.7 and 1.8 JDK's instead use tools.jar.
This other answer of mine shows locations of tools.jar and classes.jar files for mac some 1.6, 1.7 and 1.8 JDKs.
The code I ended up using is from: org.gridkit.lab::jvm Attach Api
https://mvnrepository.com/artifact/org.gridkit.lab/jvm-attach-api/1.2
Source code: http://central.maven.org/maven2/org/gridkit/lab/jvm-attach-api/1.2/
From that source code, you simply need one file: AttachAPI.java
/**
* Copyright 2013 Alexey Ragozin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gridkit.lab.jvm.attach;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* #author Alexey Ragozin (alexey.ragozin#gmail.com)
*/
class AttachAPI {
private static final LogStream LOG_ERROR = LogStream.error();
private static boolean started;
static {
try {
String javaHome = System.getProperty("java.home");
String toolsJarURL = "file:" + javaHome + "/../lib/tools.jar";
// Make addURL public
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
if (sysloader.getResourceAsStream("/com/sun/tools/attach/VirtualMachine.class") == null) {
method.invoke(sysloader, (Object) new URL(toolsJarURL));
Thread.currentThread().getContextClassLoader().loadClass("com.sun.tools.attach.VirtualMachine");
Thread.currentThread().getContextClassLoader().loadClass("com.sun.tools.attach.AttachNotSupportedException");
}
} catch (Exception e) {
LOG_ERROR.log("Java home points to " + System.getProperty("java.home") + " make sure it is not a JRE path");
LOG_ERROR.log("Failed to add tools.jar to classpath", e);
}
started = true;
};
public static void ensureToolsJar() {
if (!started) {
LOG_ERROR.log("Attach API not initialized");
}
}
}
To use this class, put it somewhere in your project and ensure you change its package accordingly. In the example below, I have placed the file in the same folder as my MyApp.java file but I've not amended the AttachAPI.java file's package statement to reflect that since I wanted to leave it pristine.
Lastly, in your main class, ensure you have a block such as the follows:
public class MyApp
{
static {
AttachAPI.ensureToolsJar();
}
public static void ensureToolsJar() {
// do nothing, just ensure call to static initializer
}
}
...
Now you will no longer need to specify a path to the tools.jar on the command line and can launch you app with simply a java -jar MyApp.jar
Not sure if it will be Eclipse or Eclipse-plugin-dev answer.
In open-source Nodeclipse project plugin.xml defines that .coffee file can be launched as coffee, coffee --compile or Node with monitor (There are 3 defined LaunchShortcuts).
First time it work fine, but then consequent launches only repeat previous LaunchType. I have found that deleting saved LaunchConfiguration (from Run -> Run Configurations) will let it run again (and then only as this type again)
The code in question is LaunchShortcut (see snippet below), however there is no any if checking, so this behavior should be deeper in Eclipse org.eclipse.debug module.
How can saved LaunchConfiguration override LaunchType ?
/**
* Launch an file,using the file information, which means using default
* launch configurations.
*
* #param file
* #param mode
*/
private void launchFile(IFile file, String mode) throws CoreException {
// check for an existing launch config for the file
String path = file.getFullPath().toString();
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type = launchManager.getLaunchConfigurationType(Constants.LAUNCH_CONFIGURATION_TYPE_ID);
ILaunchConfiguration configuration = createLaunchConfiguration(type, path, file);
DebugUITools.launch(configuration, mode);
// then execution goes in LaunchConfigurationDelegate.java launch() method
}
/**
* Create a new configuration and set useful data.
*
* #param type
* #param path
* #param file
* #return
* #throws CoreException
*/
private ILaunchConfiguration createLaunchConfiguration(ILaunchConfigurationType type, String path, IFile file) throws CoreException {
String configname = file.getFullPath().toString().replace('/', '-');
if(configname.startsWith("-")) {
configname = configname.substring(1);
}
ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(type);
for(ILaunchConfiguration config : configs) {
if(configname.equals(config.getName())) {
return config;
}
}
// create a new configuration for the file
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null, configname);
workingCopy.setAttribute(Constants.KEY_FILE_PATH, path);
setMoreAttributes(workingCopy);
return workingCopy.doSave();
}
protected void setMoreAttributes(ILaunchConfigurationWorkingCopy workingCopy) {
// stub for extension
}
Help! The code snippet is maybe not enough to answer the question, but references files and everything is in Github repository. The question was raised, because I am not sure if it is possible at all to have many Run Configuration for the same file. Then code snippets doesn't matter at all.
Update: Looking after a while at plugin.xml defines that .coffee file can be launched , I noticed that I am actually using the same <configurationType
id= "org.nodeclipse.debug.launch.LaunchConfigurationType" > in all 5 cases. However adding unique LaunchConfigurationType id for every launch makes no difference.
You can create the launch configuration with this:
Creating a Java application launch configuration
Launch groups can also be setle with this help:
Launch Group
Until here Im pretty sure you have knowledge about, so lets keep moving; You can have different launch configuration for the same file, thats handled with the launch group tool, what I dont get is if you want those different configuration for the same environment or not.
Also here Launch Configuration Types and here Adding launchers to the platform you cand find information about the struct of the launch type file
To finish here Interface ILaunchConfigurationTabGroup is the interface of the launch type tab group;
My Suggestion in codelines:
<extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
<launchConfigurationTabGroup
<"launchConfigurationType1"
<"/launchConfigurationType1">
<"launchConfigurationType2"
<"/launchConfigurationType2">
//and so on...
</launchConfigurationTabGroup>
</extension>
I'm trying to get the path to a script executing in Rhino. I would prefer to not have to pass in the directory as the first argument. I don't even have a lead on how to get it. I'm currently calling Rhino via
java -jar /some/path/to/js.jar -modules org.mozilla.javascript.commonjs.module /path/to/myscript.js
and would like myscript.js to recognize /path/to as it's dirname, regardless of where I run this script from. The only other related question & suggestion here on StackOverflow is to pass /path/to as an argument, but that is not the solution I am looking for.
It's not possible to do what you want.
The ability to detect the source of the script being run by a JavaScript interpreter is not a part of the ECMAScript language specification or the Rhino shell extensions.
However, you could write a wrapper executable program which takes a script path as its argument and executes the script in Rhino (e.g. by calling the appropriate main class) and also providing the script location as an environment variable (or similar).
/**
* Gets the name of the running JavaScript file.
*
* REQUIREMENTS:
* 1. On the Java command line, for the argument that specifies the script's
* name, there can be no spaces in it. There can be spaces in other
* arguments, but not the one that specifies the path to the JavaScript
* file. Quotes around the JavaScript file name are irrelevant. This is
* a consequence of how the arguments appear in the sun.java.command
* system property.
* 2. The following system property is available: sun.java.command
*
* #return {String} The name of the currently running script as it appeared
* on the command line.
*/
function getScriptName() {
var scriptName = null;
// Put all the script arguments into a string like they are in
// environment["sun.java.command"].
var scriptArgs = "";
for (var i = 0; i < this.arguments.length; i++) {
scriptArgs = scriptArgs + " " + this.arguments[i];
}
// Find the script name inside the Java command line.
var pattern = " (\\S+)" + scriptArgs + "$";
var scriptNameRegex = new RegExp(pattern);
var matches = scriptNameRegex.exec(environment["sun.java.command"]);
if (matches != null) {
scriptName = matches[1];
}
return scriptName;
}
/**
* Gets a java.io.File object representing the currently running script. Refer
* to the REQUIREMENTS for getScriptName().
*
* #return {java.io.File} The currently running script file
*/
function getScriptFile() {
return new java.io.File(getScriptName());
}
/**
* Gets the absolute path name of the running JavaScript file. Refer to
* REQUIREMENTS in getScriptName().
*
* #return {String} The full path name of the currently running script
*/
function getScriptAbsolutePath() {
return getScriptFile().getAbsolutePath();
}
I have a jar file (say app.jar) in a certain location available as a file/stream from an http server. The problem is that app.jar is itself a frequently updated jar file being updated regularly at the server.
I have another jar file (say load.jar) which is simply downloadable by any user.
At runtime, the user runs the load.jar, which is required to load the app.jar in a separate process keeping the app.jar in memory (no cacheing to disk), then execute the app.jar and terminate itself (load.jar).
Is it possible to be done? Any help is highly appreciated.
Thanks in advance.
Regards,
KT
---------------------------Update.
Hi,
Thanks all for the reply. However, I guess I have not given a complete picture.
An image link text is attached depicting the scenario.
4 jars (the actual common executors) are hosted on a central server. These are updated frequently (probably 3-4 times a day initially down to once a day eventually).
A local server at one of the member is hosted which is initialised.
The launcher on the local server downloads all the 4 binaries and keeps it in memory - no cacheing to disk. These jar files are self-sufficient and are not dependent on any library on the "Local Server" - they in fact invoke jars from the "Local Server".
The "client" jar eventually is hosted with the "Local Server" and forwarded to its clients on demand via webapp by the "Local Server".
Also, the Launcher needs to exit by invoking the downloaded Main jar from the server in a separate JVM.
Regards,
KT
OK. Before I put the link to the szegedi article into my previous answer (honest), I prototyped a jar-launcher that could handle URLs. Like the author said, it wasn't hard, probably isn't 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) invoke JarLauncher (below) as its main class (2) serve app.jar on a localhost port (before invoking the JarLauncher). load.jar therefore reads its arguments to figure out which app to run.
Finally (the hard bit): you have to make URLClassLoader not hit the temporary disk. As the szegedi article said, that isn't easy. Alternatively, you can write your own network-aware classloader that doesn't disk-cache, like my first suggestion loading the URL into memory as a byte-stream from a URL connection, decoding it as a JarInputStream, and satisfying calls to loadClass/findResource from that in-memory stream.
You have quite a lot of work ahead of you. Good luck.
Apologies for the size of the license text, but it lets you do what you like with the code as long as you don't 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});
}
}
I will suggest have a look at http://jcloader.sourceforge.net/
This has better flexibility and is quite feature rich.
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");
Further Edit:
I scanned the web and came across this excellent article which may also have a bearing on your question: http://www.szegedi.org/articles/remotejars.html
In which case most of what I wrote below is irrelevant, but I'll leave it anyway just in case.
Edit:
Ok, I think I'm getting a better picture of your requirements. Requirements are tricky though, so let me tell you what I think you're trying to do, and then I'll see what solutions that suggests. I probably will get this wrong, then we do it again.
Requirements:
A distributed caching mechanism for serving WebStart applications. The applications (.jars) change on a regular basis. They are self-contained. You want to have a local-cache able to serve the Webstart jar files obtained from a central server, keeping them in memory. I do not understand your requirements for Exit.
Solutions?
What you may be looking for is a web-server that can host a webapp that will read updated application jars into memory, then serve them to the webstart launcher. You will need to use a web-server such as Jetty/Tomcat, and write a simple webapp to run under it. The webapp will poll the central server for application updates, and will make the application jars available to webstart through URLs which it serves. Polling the central server probably makes more sense than having the central server push new applications to the local servers for reasons of firewall and scalability.
I don't know of any off-the-shelf webapps that do this, there may be one.
But like I said, I probably still don't get this. Requirements: got to love them.
I'm going to make some assumptions in this answer, based on your question. It sounds like you want to cache the "app.jar" from the remote machine, for the lifetime of the "load.jar" on the local machine, in order to allow isolate "load.jar" from changes to "app.jar" during its lifetime. This seems like a good idea: I would expect that if you use an URLClassLoader to bring "app.jar" into the "load.jar" space, then an update mid-way through execution could wreak havoc.
It also sounds like you don't want to have "load.jar" make a disk-based copy of the "app.jar" -- I think this is a reasonable goal: who wants to have old jar files scattered around on the machine? who wants permission issues relating to trying to write temporary files?
Given these goals, you need to find or implement a classloader that makes a snapshot of "app.jar" when "load.jar" first hits a class inside it. This isn't hard: I had to do something similar in my One-JAR JarClassLoader, which loads Jar files from inside Jar files. During startup it loads all found bytes into memory, then resolves classes on demand using that memory store. While possibly less efficient than lazy-loading, it's fast, and stable, and would solve your problem.
Unfortunately, One-JAR does not allow network (or file) resources to be cached in this manner. It uses delegation through a normal URL classloader, which would make it not cache 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. Don't be daunted by the size of this class, its a bunch of special cases to handle, well, special cases.
If I had to create something from scratch, I would subclass URLClassLoader, override the loadClass, getResource, and findResource methods (see for example line 281 where One-JAR does this for its own class-loader inversion needs), put in bytecode caching by loading the entire "app.jar" into memory as a byte array hashmap indexed by class/resource name keys (this is One-JAR again), and then you'd be cached in memory.
I hope this helps.
--simon.
Have you had a look at the URLClassloader class yet?
The JarClassloader here might be useful: http://www.java.happycodings.com/Other/code27.html