简体   繁体   中英

Java class loader independent from the system class loader for jar files

I'm trying to load a jar file inside a program to invoke different methods. I have a class that does the work, but the class loads the jar file using a URLClassLoader , which is dependent of the system class loader, so, for example, if the loaded jar performs a System.exit() it finishes the execution of the whole application, terminating the currently running Java Virtual Machine. My intention is that, if the loaded jar do this last, it only finishes the jar, not the entire application. Also, I want to be able to close the jar so I can restart it later, if needed. I'm using the following code to instantiate the required class from the jar and to invoke the methods from my application:

// Load a class with classloader = new URLClassLoader(libs);
if(loadclass == null)
    loadclass = Class.forName(classname, true, classloader);
// Execute method
if(met == null)
{
    Constructor constructor;
    if(params != null && params.length > 0)
    {
        constructor = loadclass.getConstructor(new Class[]{Object[].class});
        classinstance = constructor.newInstance(new Object[]{params});
    }
    else
    {
        constructor = loadclass.getConstructor(null);
        classinstance = constructor.newInstance(null);
    }
    return (Object)Boolean.TRUE;
}

// Generic instance
if(classinstance == null)
    classinstance = loadclass.newInstance();

// Method invocation
Method method;
if(params != null)
{
    if(params.length > 1)
        method = loadclass.getMethod(met, new Class[]{Object[].class});
    else
        method = loadclass.getMethod(met, new Class[]{Object.class});
}
else
    method = loadclass.getMethod(met);

method.setAccessible(true);
Object ret;
if(params != null)
{
    if(params.length > 1)
        ret = (Object)method.invoke(classinstance, new Object[]{params});
    else
        ret = (Object)method.invoke(classinstance, params[0]);
}
else
    ret = (Object)method.invoke(classinstance, null);

return ret;

I don't know how to decouple my URLClassLoader from the system class loader. Any help to this point is appreciated!

System.exit() will exit the process regardless of the Class Loader. Abandoning the system class loader can be done by not chaining the class loaders, however be warned. This means that all system classes will need to be loaded afreash, and they will not play nicely together. For example, comparing a string created by one class loader with another string containing the same characters from a different class loader would fail.

To prevent calls to System.exit() from succeeding, then the security manager could be configured to error.

Here is the code for System.exit()

public void exit(int status) {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkExit(status);
    }
    Shutdown.exit(status);
}

it calls security.checkExit on the security manager. Which in turn is implemented as thus:

public void checkExit(int status) {
    checkPermission(new RuntimePermission("exitVM."+status));
}

Notice the use of the permissions exitVM.<number> . Further detail on the security manager, and installing one can be read here .

Calls to System.exit() can be intercepted by a Java Agent. The following article discusses using a Java Agent to rewrite byte codes on load to insert logging statements. The same approach could be used to remove calls to System.exit.

To answer the System.exit() issue, the way is to use the SecurityManager.

In the case of discarding a loaded jar file using URLClassLoader , I find that there are some bugs related: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6630027

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6896088

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM