/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2004 * Copyright by ESO (in the framework of the ALMA collaboration), * All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package alma.acs.classloading; import java.io.File; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import alma.acs.makesupport.AcsJarFileFinder; /** * Custom class loader which correctly handles multiple occurrences of identical jar files in * "overlayed" directories. These directories would typically be ../lib, INTROOT/lib, ACSROOT/lib and ORB dirs. *
* The main purpose is to cut down the very long classpath produced otherwise by the ACS start scripts. * Only the jar file that contains this class loader must be supplied to the JVM using the "-classpath" option. * The JVM must be started with property definitions similar to: *
-Djava.system.class.loader=alma.acs.classloading.AcsSystemClassLoader
.
* -Dacs.system.classpath.jardirs=../lib/:$INTROOT/lib:$ACSROOT/lib
.
* If an operating system has a native style path separator different from ":
", it can optionally be used instead.
* URLClassLoader
.
* java.system.class.loader
.
* sun.misc.Launcher$AppClassLoader
) as the parent,
* since ACS 6.0 this CL takes over the functionality of the direct parent, and uses the original grandparent CL for parent-delegation.
* Circumventing the original parent CL after copying its CLASSPATH entries, removes the distinction between the CLASSPATH entries
* and the jar files from the acs.system.classpath.jardirs
directories.
* ../lib/ACScomponents
are not picked up by the classloader unless we add them to the CLASSPATH,
* e.g. using acsStartJava -addToClasspath
.
* sun.misc.Launcher$AppClassLoader
.
* This allows JUnit tests run, since the JUnit framework sets up their own classloader to be a child
* of the system classloader, shortcutting any "regular" child class loaders in between.
* sun.misc.Launcher$AppClassLoader
* is expected to be the parent
parameter, although no such assumption is made in the code.
*
* In the ctor, the directories given in
* It is assumed that thanks to the
* Discards requests to load classes from certain sub-packages of
* For example, jconsole would currently call this method with argument
* acs.system.classpath.jardirs
are searched for JAR files,
* which are fed as URLs into the classpath maintained by the URLClassLoader
base class.
*
* @see AcsJarFileFinder
*/
public AcsSystemClassLoader(ClassLoader parent)
{
super(new URL[0], parent.getParent());
if (!(parent instanceof URLClassLoader)) {
throw new IllegalStateException("AcsSystemClassLoader expects parent CL of type URLClassLoader!");
}
appClassLoader = (URLClassLoader) parent;
verbose = Boolean.getBoolean(PROPERTY_CLASSLOADERVERBOSE);
Listjava.system.class.loader
property,
* this AcsSystemClassLoader is a direct child of the application system class loader
* which normally would handle the CLASSPATH.
*/
private void prependCLASSPATHJars(Listsun.
or com.sun.
* by throwing a ClassNotFoundException
.
* The JDK libs try to search (e.g. during ACS container startup) for some optional system classes such as
* sun.text.resources.DateFormatZoneData_en_US
or sun.util.logging.resources.logging_en
.
* We know that ALMA jar files do not contain any classes in those packages, and can thus speed up the applications,
* in cases where those classes have already been searched unsuccessfully by any parent class loaders,
* which as the last step desparately would ask this class loader, which would cause a search through all jar files.
* sun.awt.resources.
* com.sun.swing.internal.plaf.
*/
protected Class> findClass(String name) throws ClassNotFoundException
{
if (optimizer.isClassKnownToBeUnavailable(name)) {
throw new ClassNotFoundException("ACS and application software are not supposed to deliver a class like '"
+ name + "' and therefore AcsSystemClassLoader won't attempt to load it (for IO optimization).");
}
Class> clazz = null;
try {
// System.out.println("****AcsSystemClassLoader will try to find class " + name);
clazz = super.findClass(name);
}
catch (ClassNotFoundException e) {
if (verbose) {
System.err.println(AcsSystemClassLoader.class.getName() + " failed to load class " + name);
e.printStackTrace();
}
throw e;
}
return clazz;
}
/**
* This method, even though private, allows jconsole and possibly similar profilers and other tools
* to add their required jar files,
* see {@linkplain java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch(java.util.jar.JarFile)}.
* /usr/java/jdk1.6.0_02/jre/lib/management-agent.jar
.
*
* @since ACS 7.0
*/
private void appendToClassPathForInstrumentation(String jarPathName) {
File jarFile = new File(jarPathName);
try {
addURL(jarFile.toURI().toURL());
System.out.println("AcsSystemClassLoader#appendToClassPathForInstrumentation called with jar file " + jarPathName);
} catch (MalformedURLException ex) {
System.err.println("AcsSystemClassLoader#appendToClassPathForInstrumentation failed with MalformedURLException for jar file " + jarPathName);
}
}
}