Java/Reflection/ClassLoader
Содержание
- 1 A class loader which loads classes using a searchlist of other classloaders
- 2 A class to simplify access to resources through the classloader
- 3 Analyze ClassLoader hierarchy for any given object or class loader
- 4 Class Finder
- 5 Class For Name
- 6 Context ClassLoader
- 7 Determining from Where a Class Was Loaded
- 8 does Class Exist
- 9 Dynamically Reloading a Modified Class
- 10 Equivalently to invoking Thread.currentThread().getContextClassLoader().loadClass(className); but it supports primitive types and array classes of object types or primitive types.
- 11 Force the given class to be loaded fully.
- 12 Get a compatible constructor for the given value type
- 13 Get the path from where a class is loaded
- 14 Jar Class Loader
- 15 Java interpreter replacement
- 16 Load Class
- 17 Load classes
- 18 Load class from Thread"s ContextClassLoader, classloader of derived class or the system ClassLoader
- 19 Loading a Class That Is Not on the Classpath
- 20 Return the context classloader.
- 21 Unqualified names
- 22 Using the forName() method
- 23 Utility to essentially do Class forName and allow configurable Classloaders.
- 24 Various Class Loader utilities
- 25 Zip Class Loader
A class loader which loads classes using a searchlist of other classloaders
<source lang="java">
/*
* SearchlistClassLoader: class loader which loads classes using a searchlist * * Copyright (C) 2007-2009 Nik Trevallyn-Jones, Sydney Austraila. * * Author: Nik Trevallyn-Jones, nik777@users.sourceforge.net * $Id: Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program 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 version 2 of the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * with this program. If not, version 2 of the license is available * from the GNU project, at http://www.gnu.org. */
/*
* History: * V1.2 NTJ, Jan 2009. * - Fixed NullPointerException when searchlist was empty. * - Added support for findLibrary() * * V1.1 NTJ, Aug 2007. * - Reworked the searchlist storage, and moved searchlist * traversal into a new method: getLoader(int, byte). * -- traversal should be somewhat faster; searchMode can be * changed even after ClassLoaders have been added; * - Reworked findClass(name) so that all classes located * through shared loaders are associated with the shared * loader, and all classes located through non-shared loaders * are associated with the owning SearchlistClassLoader. * - removed "recent" loader code. * * V1.0 NTJ, April 2007. * - Initial coding, based on a RemoteClassLoader used in AOS. */
import java.util.ArrayList; import java.util.Vector; import java.util.Hashtable; import java.net.URL; import java.net.URLClassLoader; import java.io.*; /**
* A class loader which loads classes using a searchlist of * other classloaders. * **
The classloaders in the searchlist are of two types: shared and * non-shared. A shared classloader may be in use by other code, and * so no duplicates should be made of the classes in the loaders. *
A non-shared classloader is private to this SearchlistClassLoader, and * so there is no possibility that other code could be using them. To avoid * problems of isolation, all classes loaded through non-shared loaders are * defined as having been loaded by the SearchlistClassLoader itself. This * ensures the JVM can find the correct loader when loading associated * classes (including shared classes). * *
The SearchlistClassLoader API therefore makes a clear distinction * between shared and non-shared classloaders. *
The {@link #add(ClassLoader)} method adds an existing classloader * which means the added classloader is treated as being shared. *
The {@link #add(URL)} method adds a new internally created classloader * which loads the content associated with the specified URL, which means the * internally created classloader is non-shared. *
* *
SearchlistClassLoader therefore also allows control over the order in * which classloaders are searched, through the {@link #setSearchMode(byte)} * method. * *
The possible searchmodes are:
-
*
- SHARED
*
added classloaders are searched before added URLs, which causes * an existing class instance to be used (and SHARED) in preference to * loading (or creating) a NON-SHARED duplicate. * * - NONSHARED
*
added URLs are searched before added classloaders. This will * create a NON-SHARED copy of a class (ie a duplicate) in preference to * using a SHARED one from another classloader. * * - ORDERED
*
added classloaders and URLs are searched in the order in which * they were added to the searchlist. *
* **
There is also a method which retrieves a class without searching * any added classloaders. This effectively retrieves the canonical * instance of the requested class (see {@link #loadLocalClass(String)} * and {@link #getLocalResource(String)}). *
Implementation notes:.
*
*
Because each class object is associated with the classloader which
* defined it (see ClassLoader.defineClass(...)), SearchlistClassLoader
* must associate itself with all class objects it loads
* through non-shared loaders, and similarly must not associate
* itself with class objects loaded through shared loaders.
* (See {@link #findClass(String)}.)
*
*
The structure of the internal ClassLoader methods is as per the
* instructions in {@link java.lang.ClassLoader}. While I don"t think this is
* necessary any longer, it was quite easy to comply with the instructions.
*/
public class SearchlistClassLoader extends ClassLoader
{
protected Vector list, search;
protected Hashtable cache;
protected Loader content = null;
protected byte searchMode = SHARED;
protected int divide = 0;
/** search mode enums */
public static final byte SHARED = 0x1;
public static final byte NONSHARED = 0x2;
public static final byte ORDERED = 0x3;
protected static final URL EMPTY_URL[] = new URL[0];
/**
* create a SearchlistClassLoader.
*/
public SearchlistClassLoader()
{}
/**
* create a SearchlistClassLoader.
*/
public SearchlistClassLoader(ClassLoader parent)
{ super(parent); }
/**
* create a SearchlistClassLoader.
*/
public SearchlistClassLoader(URL url[])
{ content = new Loader(new URLClassLoader(url), false); }
/**
* create a SearchlistClassLoader.
*/
public SearchlistClassLoader(URL url[], ClassLoader parent)
{
super(parent);
content = new Loader(new URLClassLoader(url), false);
}
/**
* set the search mode.
*
* @param mode enum for the searchmode: SHARED, NONSHARED, ORDERED
*/
public void setSearchMode(byte mode)
{
byte prev = searchMode;
searchMode = mode;
if (searchMode <= 0 || searchMode > ORDERED) {
System.out.println("SearchlistClassLoader.setSearchMode: " +
"Invalid search mode: " + mode +
"; defaulting to SHARED.");
searchMode = SHARED;
}
}
/**
* add a (shared) classloader to the searchlist.
*
* The loader is added to the list as a shared loader.
*
* @param loader the ClassLoader to add to the searchlist.
*/
public void add(ClassLoader loader)
{
Loader ldr = new Loader(loader, true);
// store loaders in order in list
if (list == null) list = new Vector(16);
list.add(ldr);
// store shared loaders in front of non-shared loaders in search.
if (search == null) search = new Vector(16);
if (search.size() > divide) search.add(divide, ldr);
else search.add(ldr);
divide++;
}
/**
* add a (non-shared) URL to the searchlist.
*
* Creates a new URLClassLoader and adds it to the searchlist as a
* non-shared classloader.
*
* @param url the URL to add to the searchlist.
*/
public void add(URL url)
{
Loader ldr = new Loader(new URLClassLoader(new URL[] { url }), false);
// store loaders in order in list
if (list == null) list = new Vector(16);
list.add(ldr);
// store non-shared loaders after shared loaders in search
if (search == null) search = new Vector(16);
search.add(ldr);
}
/**
* return the array of URLs used locally by this class loader
*/
public URL[] getURLs()
{
return (content != null
? ((URLClassLoader) content.loader).getURLs()
: EMPTY_URL
);
}
/**
* return the list of URLs in the search list
*/
public URL[] getSearchPath()
{
Loader ldr;
URL[] url;
int j;
ArrayList path = new ArrayList(8);
for (int i = 0; (ldr = getLoader(i++, searchMode)) != null; i++) {
if (ldr.loader instanceof SearchlistClassLoader)
url = ((SearchlistClassLoader) ldr.loader).getSearchPath();
else if (ldr.loader instanceof URLClassLoader)
url = ((URLClassLoader) ldr.loader).getURLs();
else
url = null;
if (url != null) {
for (j = 0; j < url.length; j++)
path.add(url[j]);
}
}
return (path.size() > 0 ? (URL[]) path.toArray(EMPTY_URL) : EMPTY_URL);
}
/**
* Return the local class instance for name.
*
*
This does not search the searchlist. Only classes loaded
* directly by this loader or its parent are returned.
*
*
This method can be used to retrieve the canonical instance
* of a class.
* If this method is called on a set of SearchlistClassLoaders, then
* the only classloader which will return the class is the one which
* originally loaded it (assuming no duplicates have been created yet).
*
* @param name the fully-qualified name of the class
* @return the loaded class.
*
* @throws ClassNotFoundException if the class is not found.
*/
public Class loadLocalClass(String name)
throws ClassNotFoundException
{
ClassNotFoundException err = null;
if (getParent() != null) {
try {
return getParent().loadClass(name);
} catch (ClassNotFoundException e) {
err = e;
}
}
if (content != null) {
// try the cache first
Class result = (cache != null ? (Class) cache.get(name) : null);
if (result != null) return result;
// try loading the class data
byte[] data = loadClassData(content.loader, name);
if (data != null) {
// define the class
result = defineClass(name, data, 0, data.length);
if (result != null) {
//System.out.println("defined class: " + name);
// cache the result
if (cache == null) cache = new Hashtable(1024);
cache.put(name, result);
return result;
}
}
}
throw (err != null ? err : new ClassNotFoundException(name));
}
/**
* Return the URL for the local resource specified by name.
*
*
This does not search the searchlist. Only resources loaded
* directly by this loader or its parent are returned.
*
*
This method can be used to retrieve the canonical URL for a
* resource.
* If this method is called on a set of SearchlistClassLoaders, then
* the only classloader which will return the resource is the one which
* originally loaded it (assuming no duplicates have been created yet).
*
* @param name the fully-qualified name of the resource.
* @return the located URL, or null.
*/
public URL getLocalResource(String name)
{
URL result = null;
if (getParent() != null) {
result = getParent().getResource(name);
}
if (result == null && content != null) {
result = content.loader.getResource(name);
}
return result;
}
/**
* Return a Class object for the specified class name.
*
* @overloads java.lang.ClassLoader#findClass(String)
*
* Traverses the searchlist looking for a classloader which can return
* the specified class.
*
*
This method is called by inherited loadClass() methods whenever
* a class cannot be found in the parent classloader.
*
*
If the class is found using a shared loader, then it is
* returned directly. If the class is found using a non-shared
* loader, then the actual class object is defined by the containing
* SearchlistClassLoader, which causes Java to associate the new class
* object with the SearchlistClassLaoder, rather then the non-shared
* loader.
*
* @param name the fully-qualified name of the class
* @return the loaded class object
*
* @throws ClassNotFoundException if the class could not be loaded.
*/
public Class findClass(String name)
throws ClassNotFoundException
{
Loader ldr;
Throwable err = null;
Class result;
byte[] data;
for (int i = 0; (ldr = getLoader(i, searchMode)) != null; i++) {
try {
// for shared loaders - just try getting the class
if (ldr.shared)
return ldr.loader.loadClass(name);
// for non-shared loaders, we have to define the class manually
else {
// check the cache first
result = (cache != null ? (Class) cache.get(name) : null);
if (result != null) return result;
// try loading the class
data = loadClassData(ldr.loader, name);
if (data != null) {
// data loaded, define the class
result = defineClass(name, data, 0, data.length);
if (result != null) {
//System.out.println("defined class: " + name);
// cache the result
if (cache == null) cache = new Hashtable(1024);
cache.put(name, result);
return result;
}
}
}
}
catch (Throwable t) {
err = t;
}
}
throw (err != null
? new ClassNotFoundException(name, err)
: new ClassNotFoundException(name)
);
}
/**
* find a resource using the searchlist.
*
* @overloads ClassLoader#findResource(String)
*
* NoteInherited behaviour of loadClass() and getResource() means
* that this method is not called if our parent classloader has
* already found the data.
*
* @param path the fully-qualified name of the resource to retrieve
* @return the URL if the resource is found, and null otherwise.
*/
public URL findResource(String path)
{
System.out.println("findResource: looking in " + this + " for " +
path);
URL url = null;
Loader ldr;
for (int i = 0; (ldr = getLoader(i, searchMode)) != null; i++) {
url = ldr.loader.getResource(path);
if (url != null) {
System.out.println("found " + path + " in loader: " +
ldr.loader);
break;
}
}
return url;
}
/**
* return the pathname to the specified native library.
*
* If the library is not found on the searchpath, then null
* is returned, indicating to the Java machine that it should search
* java.library.path.
*
* @param libname - the String name of the library to find
* @return the full path to the found library file, or null.
*/
public String findLibrary(String libname)
{
String fileName = System.mapLibraryName(libname);
System.out.println("findLibrary: looking in " + this + " for " +
libname + " as " + fileName);
int i, j;
URL[] url;
File dir, file;
Loader ldr;
for (i = 0; (ldr = getLoader(i++, searchMode)) != null; i++) {
if (ldr.loader instanceof SearchlistClassLoader)
url = ((SearchlistClassLoader) ldr.loader).getSearchPath();
else if (ldr.loader instanceof URLClassLoader)
url = ((URLClassLoader) ldr.loader).getURLs();
else
url = null;
if (url != null) {
for (j = 0; j < url.length; j++) {
if (!url[j].getProtocol().equalsIgnoreCase("file"))
continue;
try {
dir = new File(url[j].toURI()).getParentFile();
file = new File(dir, fileName);
if (file.exists()) {
System.out.println("found: " +
file.getAbsolutePath());
return file.getAbsolutePath();
}
} catch (Exception e) {
System.out.println("Ignoring url: " + url[j] + ": "
+ e);
}
}
}
}
// nothing found, use java.library.path
return null;
}
/**
* return the correct classloader for the specified position in the
* search.
*
* @param index the position (step) in the search process
* @param mode the search mode to use
*
* @return The corresponding Loader or null
*/
protected Loader getLoader(int index, byte mode)
{
// content is always the first loader searched
if (content != null) {
if (index == 0) return content;
else index--;
}
if (index < 0 || list == null || index >= list.size()) return null;
Loader result;
switch (mode) {
case SHARED:
// return shared loaders before non-shared loaders
result = (Loader) search.get(index);
break;
case NONSHARED:
// return non-shared loaders before shared loaders
{
int pos = index + divide;
result = (Loader) (pos < search.size()
? search.get(pos)
: search.get(pos-divide)
);
}
break;
default:
// return loaders in the order in which they were added
result = (Loader) list.get(index);
}
return result;
}
/**
* load the byte data for a class definition.
*
* @param name the fully-qualified class name
* @return a byte[] containing the class bytecode or null
*/
protected byte[] loadClassData(ClassLoader cl, String name)
{
ByteArrayOutputStream barray;
byte buff[];
int len;
InputStream in = cl.getResourceAsStream(translate(name, ".", "/")
+ ".class");
if (in == null) return null;
try {
barray = new ByteArrayOutputStream(1024*16);
buff = new byte[1024];
do {
len = in.read(buff, 0, buff.length);
if (len > 0) barray.write(buff, 0, len);
} while (len >= 0);
return (barray.size() > 0 ? barray.toByteArray() : null);
} catch (Exception e) {
return null;
}
}
/**
* translate matching chars in a string.
*
* @param str the String to translate
* @param match the list of chars to match, in a string.
* @param replace the list of corresponding chars to replace matched chars
* with.
*
*
* Eg: translate("the dog.", "o.", "i") * returns "the dig", because "o" is replaced with "i", and "." is * replaced with nothing (ie deleted). *
* * @return the result as a string. */ public static String translate(String str, String match, String replace) { StringBuffer b = new StringBuffer(str.length()); int pos = 0; char c = 0; if (match == null) match = ""; if (replace == null) replace = ""; boolean copy = (match.length() != 0 && match.length() >= replace.length()); // loop over the input string int max = str.length(); for (int x = 0; x < max; x++) { c = str.charAt(x); pos = match.indexOf(c); // if found c in "match" if (pos >= 0) { // translate if (pos < replace.length()) b.append(replace.charAt(pos)); } // copy else if (copy || replace.indexOf(c) >= match.length()) b.append(c); // otherwise, effectively, delete... } return b.toString(); } /** * internal class to store the state of each searchable ClassLoader. * * The containing SearchlistClassLoader needs to know information about * each loader in the list. */ protected static class Loader { ClassLoader loader = null; // the actual classloader boolean shared = false; // shared flag Loader(ClassLoader loader, boolean shared) { this.loader = loader; this.shared = shared; } }
}
</source>
A class to simplify access to resources through the classloader
<source lang="java">
/*
* Copyright 2004 Clinton Begin * * 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. */
import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; import java.util.Properties; /**
* A class to simplify access to resources through the classloader. */
public class Resources extends Object {
private static ClassLoader defaultClassLoader; /** * Charset to use when calling getResourceAsReader. * null means use the system default. */ private static Charset charset; private Resources() { } /** * Returns the default classloader (may be null). * * @return The default classloader */ public static ClassLoader getDefaultClassLoader() { return defaultClassLoader; } /** * Sets the default classloader * * @param defaultClassLoader - the new default ClassLoader */ public static void setDefaultClassLoader(ClassLoader defaultClassLoader) { Resources.defaultClassLoader = defaultClassLoader; } /** * Returns the URL of the resource on the classpath * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static URL getResourceURL(String resource) throws IOException { return getResourceURL(getClassLoader(), resource); } /** * Returns the URL of the resource on the classpath * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static URL getResourceURL(ClassLoader loader, String resource) throws IOException { URL url = null; if (loader != null) url = loader.getResource(resource); if (url == null) url = ClassLoader.getSystemResource(resource); if (url == null) throw new IOException("Could not find resource " + resource); return url; } /** * Returns a resource on the classpath as a Stream object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static InputStream getResourceAsStream(String resource) throws IOException { return getResourceAsStream(getClassLoader(), resource); } /** * Returns a resource on the classpath as a Stream object * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException { InputStream in = null; if (loader != null) in = loader.getResourceAsStream(resource); if (in == null) in = ClassLoader.getSystemResourceAsStream(resource); if (in == null) throw new IOException("Could not find resource " + resource); return in; } /** * Returns a resource on the classpath as a Properties object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Properties getResourceAsProperties(String resource) throws IOException { Properties props = new Properties(); InputStream in = null; String propfile = resource; in = getResourceAsStream(propfile); props.load(in); in.close(); return props; } /** * Returns a resource on the classpath as a Properties object * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Properties getResourceAsProperties(ClassLoader loader, String resource) throws IOException { Properties props = new Properties(); InputStream in = null; String propfile = resource; in = getResourceAsStream(loader, propfile); props.load(in); in.close(); return props; } /** * Returns a resource on the classpath as a Reader object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Reader getResourceAsReader(String resource) throws IOException { Reader reader; if (charset == null) { reader = new InputStreamReader(getResourceAsStream(resource)); } else { reader = new InputStreamReader(getResourceAsStream(resource), charset); } return reader; } /** * Returns a resource on the classpath as a Reader object * * @param loader The classloader used to load the resource * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static Reader getResourceAsReader(ClassLoader loader, String resource) throws IOException { Reader reader; if (charset == null) { reader = new InputStreamReader(getResourceAsStream(loader, resource)); } else { reader = new InputStreamReader(getResourceAsStream(loader, resource), charset); } return reader; } /** * Returns a resource on the classpath as a File object * * @param resource The resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static File getResourceAsFile(String resource) throws IOException { return new File(getResourceURL(resource).getFile()); } /** * Returns a resource on the classpath as a File object * * @param loader - the classloader used to load the resource * @param resource - the resource to find * @return The resource * @throws IOException If the resource cannot be found or read */ public static File getResourceAsFile(ClassLoader loader, String resource) throws IOException { return new File(getResourceURL(loader, resource).getFile()); } /** * Gets a URL as an input stream * * @param urlString - the URL to get * @return An input stream with the data from the URL * @throws IOException If the resource cannot be found or read */ public static InputStream getUrlAsStream(String urlString) throws IOException { URL url = new URL(urlString); URLConnection conn = url.openConnection(); return conn.getInputStream(); } /** * Gets a URL as a Reader * * @param urlString - the URL to get * @return A Reader with the data from the URL * @throws IOException If the resource cannot be found or read */ public static Reader getUrlAsReader(String urlString) throws IOException { return new InputStreamReader(getUrlAsStream(urlString)); } /** * Gets a URL as a Properties object * * @param urlString - the URL to get * @return A Properties object with the data from the URL * @throws IOException If the resource cannot be found or read */ public static Properties getUrlAsProperties(String urlString) throws IOException { Properties props = new Properties(); InputStream in = null; String propfile = urlString; in = getUrlAsStream(propfile); props.load(in); in.close(); return props; } /** * Loads a class * * @param className - the class to load * @return The loaded class * @throws ClassNotFoundException If the class cannot be found (duh!) */ public static Class classForName(String className) throws ClassNotFoundException { Class clazz = null; try { clazz = getClassLoader().loadClass(className); } catch (Exception e) { // Ignore. Failsafe below. } if (clazz == null) { clazz = Class.forName(className); } return clazz; } /** * Creates an instance of a class * * @param className - the class to create * @return An instance of the class * @throws ClassNotFoundException If the class cannot be found (duh!) * @throws InstantiationException If the class cannot be instantiaed * @throws IllegalAccessException If the class is not public, or other access problems arise */ public static Object instantiate(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException { return instantiate(classForName(className)); } /** * Creates an instance of a class * * @param clazz - the class to create * @return An instance of the class * @throws InstantiationException If the class cannot be instantiaed * @throws IllegalAccessException If the class is not public, or other access problems arise */ public static Object instantiate(Class clazz) throws InstantiationException, IllegalAccessException { try { return clazz.newInstance(); } catch (Exception e) { // Try alternative...theoretically should fail for the exact same // reason, but in case of a weird security manager, this will help // some cases. //return clazz.newInstance(); return clazz.newInstance(); } } private static ClassLoader getClassLoader() { if (defaultClassLoader != null) { return defaultClassLoader; } else { return Thread.currentThread().getContextClassLoader(); } } public static Charset getCharset() { return charset; } /** * Use this method to set the Charset to be used when * calling the getResourceAsReader methods. This will * allow iBATIS to function properly when the system default * encoding doesn"t deal well with unicode (IBATIS-340, IBATIS-349) * * @param charset */ public static void setCharset(Charset charset) { Resources.charset = charset; }
}
</source>
Analyze ClassLoader hierarchy for any given object or class loader
<source lang="java">
/*
* Copyright 2002-2005 the original author or authors. * * 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. */
/**
* Utility class for diagnostic purposes, to analyze the * ClassLoader hierarchy for any given object or class loader. * * @author Rod Johnson * @author Juergen Hoeller * @since 02 April 2001 * @see java.lang.ClassLoader */
public abstract class ClassLoaderUtils {
/** * Show the class loader hierarchy for this class. * Uses default line break and tab text characters. * @param obj object to analyze loader hierarchy for * @param role a description of the role of this class in the application * (e.g., "servlet" or "EJB reference") * @return a String showing the class loader hierarchy for this class */ public static String showClassLoaderHierarchy(Object obj, String role) { return showClassLoaderHierarchy(obj, role, "\n", "\t"); } /** * Show the class loader hierarchy for this class. * @param obj object to analyze loader hierarchy for * @param role a description of the role of this class in the application * (e.g., "servlet" or "EJB reference") * @param lineBreak line break * @param tabText text to use to set tabs * @return a String showing the class loader hierarchy for this class */ public static String showClassLoaderHierarchy(Object obj, String role, String lineBreak, String tabText) { String s = "object of " + obj.getClass() + ": role is " + role + lineBreak; return s + showClassLoaderHierarchy(obj.getClass().getClassLoader(), lineBreak, tabText, 0); } /** * Show the class loader hierarchy for the given class loader. * Uses default line break and tab text characters. * @param cl class loader to analyze hierarchy for * @return a String showing the class loader hierarchy for this class */ public static String showClassLoaderHierarchy(ClassLoader cl) { return showClassLoaderHierarchy(cl, "\n", "\t"); } /** * Show the class loader hierarchy for the given class loader. * @param cl class loader to analyze hierarchy for * @param lineBreak line break * @param tabText text to use to set tabs * @return a String showing the class loader hierarchy for this class */ public static String showClassLoaderHierarchy(ClassLoader cl, String lineBreak, String tabText) { return showClassLoaderHierarchy(cl, lineBreak, tabText, 0); } /** * Show the class loader hierarchy for the given class loader. * @param cl class loader to analyze hierarchy for * @param lineBreak line break * @param tabText text to use to set tabs * @param indent nesting level (from 0) of this loader; used in pretty printing * @return a String showing the class loader hierarchy for this class */ private static String showClassLoaderHierarchy(ClassLoader cl, String lineBreak, String tabText, int indent) { if (cl == null) { ClassLoader ccl = Thread.currentThread().getContextClassLoader(); return "context class loader=[" + ccl + "] hashCode=" + ccl.hashCode(); } StringBuffer buf = new StringBuffer(); for (int i = 0; i < indent; i++) { buf.append(tabText); } buf.append("[").append(cl).append("] hashCode=").append(cl.hashCode()).append(lineBreak); ClassLoader parent = cl.getParent(); return buf.toString() + showClassLoaderHierarchy(parent, lineBreak, tabText, indent + 1); }
}
</source>
Class Finder
<source lang="java">
/*
* Copyright 2007 (C) TJDO. * All rights reserved. * * This software is distributed under the terms of the TJDO License version 1.0. * See the terms of the TJDO License in the documentation provided with this software. * * $Id: ClassFinder.java,v 1.1 2007/10/03 01:20:37 jackknifebarber Exp $ */
import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.WeakHashMap;
/**
* Used to load classes according to the rules defined in the JDO spec. * See section 12.5 of the JDO 1.0.1 spec. * <p> * This class also provides a {@link #classForName(String,boolean,ClassLoader) * static method} for loading classes that utilizes a cache. * The cache contains class names that were previously not found, * organized by the loader that failed to find them. * This speeds up cases where attempts to load the same non-existent class are * repeated many times. * * @author * @version $Revision: 1.1 $ */
public class ClassFinder {
private static final Map findersByLoader = new WeakHashMap(); private static final Map nonExistentClassNamesByLoader = new WeakHashMap();
/** * Returns the class finder instance associated with the context class * loader of the calling thread. */ public static ClassFinder getInstance() { return getInstance(getContextClassLoaderPrivileged()); } /** * Returns the class finder instance associated with the specified class * loader. * The specified loader becomes the finder"s "original context class loader" * for the algorithm implemented by * {@link #classForName(String,boolean,Class)}. * * @param ctxLoader * the context class loader */ public static synchronized ClassFinder getInstance(ClassLoader ctxLoader) { ClassFinder cf = (ClassFinder)findersByLoader.get(ctxLoader); if (cf == null) findersByLoader.put(ctxLoader, cf = new ClassFinder(ctxLoader)); return cf; } /** * Calls getContextClassLoader() for the current thread in a doPrivileged * block. * * @return * The context class loader of the current thread. * @exception SecurityException * If getContextClassLoader() fails. */ private static ClassLoader getContextClassLoaderPrivileged() throws SecurityException { return (ClassLoader)AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return Thread.currentThread().getContextClassLoader(); } } ); }
private final ClassLoader origContextClassLoader; private ClassFinder(ClassLoader origContextClassLoader) { this.origContextClassLoader = origContextClassLoader; } /** * Returns the Class object associated with the class or interface * with the given string name. * <p> * This method implements the algorithm described in section 12.5 of the JDO * 1.0.1 spec. * It attempts to load the class using up to three loaders:*
-
*
- The loader that loaded the class or instance referred to in the API * that caused this class to be loaded (the context class). *
- The loader returned in the current context by * Thread.getContextClassLoader(). *
- The loader returned by Thread.getContextClassLoader() at * the time this ClassFinder was constructed (which should equate * to the time of PersistenceManagerFactory.getPersistenceManager()). * *
*
* @param className
* fully qualified name of the desired class
* @param initialize
* whether the class must be initialized
* @param contextClass
* another class to serve as context for the loading of the named
* class, or null
if there is no such other class
*
* @return
* class object representing the desired class
* @exception ClassNotFoundException
* if the class cannot be located
*/
public Class classForName(String className, boolean initialize, Class contextClass) throws ClassNotFoundException
{
if (contextClass != null)
{
try
{
return classForName(className, initialize, contextClass.getClassLoader());
}
catch (ClassNotFoundException e)
{
}
}
return classForName(className, initialize);
}
/**
* Returns the Class object associated with the class or interface
* with the given string name.
* <p>
* This method is equivalent to:
* * classForName(className, initialize, null) *
* * @param className * fully qualified name of the desired class * @param initialize * whether the class must be initialized * * @return * class object representing the desired class * @exception ClassNotFoundException * if the class cannot be located */ public Class classForName(String className, boolean initialize) throws ClassNotFoundException { try { return classForName(className, initialize, getContextClassLoaderPrivileged()); } catch (ClassNotFoundException e) { return classForName(className, initialize, origContextClassLoader); } } /** * Returns the Class object associated with the class or interface * with the given string name. * <p> * This method is functionally equivalent to *{@link Class#forName(String,boolean,ClassLoader)} * except that it maintains a cache of class names that are not * found. * In many cases, especially in an app server environment, searching for * non-existent classes can be a slow process. * It"s important because some things in TJDO, notably the macro mechanism * used in e.g. view definitions, will search for class names that don"t * exist. * * @param className * fully qualified name of the desired class * @param initialize * whether the class must be initialized * @param loader * class loader from which the class must be loaded * * @return * class object representing the desired class * @exception ClassNotFoundException * if the class cannot be located */ public static Class classForName(String className, boolean initialize, ClassLoader loader) throws ClassNotFoundException { Set names; synchronized (nonExistentClassNamesByLoader) { names = (Set)nonExistentClassNamesByLoader.get(loader); if (names == null) nonExistentClassNamesByLoader.put(loader, names = new HashSet()); else { if (names.contains(className)) throw new ClassNotFoundException(className + " (cached from previous lookup attempt)"); } } try { return Class.forName(className, initialize, loader); } catch (ClassNotFoundException e) { synchronized (nonExistentClassNamesByLoader) { names.add(className); } throw e; } } /** * Returns a hash code value for this object. */ public int hashCode() { return origContextClassLoader.hashCode(); } /** * Indicates whether some object is "equal to" this one. * Two ClassFinder objects are considered equal if their original * context class loaders are all equal. * * @param obj * the reference object with which to compare * * @return * true if this object is equal to the obj argument; * false otherwise. */ public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof ClassFinder)) return false; ClassFinder cf = (ClassFinder)obj; return origContextClassLoader.equals(cf.origContextClassLoader); }
}
</source>
Class For Name
<source lang="java">
// $Id: ReflectionHelper.java 16271 2009-04-07 20:20:12Z hardy.ferentschik $ /*
- JBoss, Home of Professional Open Source
- Copyright 2008, Red Hat Middleware LLC, and individual contributors
- by the @authors tag. See the copyright.txt in the distribution for a
- full listing of individual contributors.
- 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.
- /
import java.beans.Introspector; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; /**
* Some reflection utility methods. * * @author Hardy Ferentschik */
public class ReflectionHelper {
public static Class<?> classForName(String name, Class<?> caller) throws ClassNotFoundException { try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if ( contextClassLoader != null ) { return contextClassLoader.loadClass( name ); } } catch ( Throwable e ) { // ignore } return Class.forName( name, true, caller.getClassLoader() ); }
}
</source>
Context ClassLoader
<source lang="java">
/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/
import java.io.InputStream; import java.net.URL; /**
* Utility methods dealing with the context class loader. Fail-over is provided to the default class loader. * * @author */
public final class ContextClassLoader {
/** * Loads a class starting from the given class loader (can be null, then use default class loader) * * @param loader * @param name of class to load * @return * @throws ClassNotFoundException */ public static Class forName(final ClassLoader loader, final String name) throws ClassNotFoundException { Class klass = null; if (loader != null) { klass = Class.forName(name, false, loader); } else { klass = Class.forName(name, false, ClassLoader.getSystemClassLoader()); } return klass; }
/** * Loads a class from the context class loader or, if that fails, from the default class loader. * * @param name is the name of the class to load. * @return aClass
object. * @throws ClassNotFoundException if the class was not found. */ public static Class forName(final String name) throws ClassNotFoundException { Class cls = null; try { cls = Class.forName(name, false, Thread.currentThread().getContextClassLoader()); } catch (Exception e) { cls = Class.forName(name); } return cls; } /** * Loads a resource from the context class loader or, if that fails, from the default class loader. * * @param name is the name of the resource to load. * @return aURL
object. */ public static URL loadResource(final String name) { try { return Thread.currentThread().getContextClassLoader().getResource(name); } catch (Exception e) { return ClassLoader.class.getClassLoader().getResource(name); } }
// /**
// * Loads a resource from the context class loader or, if that fails, from the default class loader, as stream
// *
// * @param name is the name of the resource to load.
// * @return a InputStream
object.
// */
// public static InputStream getResourceAsStream(final String name) {
// InputStream stream = null;
// ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
// if (contextClassLoader != null) {
// stream = contextClassLoader.getResourceAsStream(name);
// }
// if (stream == null) {
// ClassLoader classLoader = ClassLoader.class.getClassLoader();
// if (classLoader != null) {
// stream = classLoader.getResourceAsStream(name);
// }
// }
// return stream;
// }
/** * Returns the context class loader. * * @return the context class loader */ public static ClassLoader getLoader() { ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (loader == null) { loader = ClassLoader.class.getClassLoader(); } return loader; }
}
</source>
Determining from Where a Class Was Loaded
<source lang="java">
import java.net.URL; import java.security.CodeSource; import java.security.ProtectionDomain; public class Main {
public Main() { Class cls = this.getClass(); ProtectionDomain pDomain = cls.getProtectionDomain(); CodeSource cSource = pDomain.getCodeSource(); URL loc = cSource.getLocation(); } public static void main(String[] argv) throws Exception { }
}
</source>
does Class Exist
<source lang="java">
public class Main {
public static boolean doesClassExist(String name) { try { Class c = Class.forName(name); if (c != null) return true; } catch (ClassNotFoundException e) { // Class not found } catch (Exception e) { e.printStackTrace(); } return false; }
}
</source>
Dynamically Reloading a Modified Class
<source lang="java">
import java.io.File; import java.net.URL; import java.net.URLClassLoader; class MyClass{
public String myMethod() { return "a message"; }
} public class Main {
public static void main(String[] argv) throws Exception { URL[] urls = null; File dir = new File(System.getProperty("user.dir") + File.separator + "dir" + File.separator); URL url = dir.toURI().toURL(); urls = new URL[] { url }; ClassLoader cl = new URLClassLoader(urls); Class cls = cl.loadClass("MyClass"); MyClass myObj = (MyClass) cls.newInstance(); }
}
</source>
Equivalently to invoking Thread.currentThread().getContextClassLoader().loadClass(className); but it supports primitive types and array classes of object types or primitive types.
<source lang="java">
/*
* JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */
import java.lang.reflect.Array; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; /**
* A collection of Class
utilities.
*
* @version $Revision: 2787 $
* @author
* @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis<a/>
*/
@SuppressWarnings("unchecked") public final class Classes {
/** The string used to separator packages */ public static final String PACKAGE_SEPARATOR = "."; /** The characther used to separator packages */ public static final char PACKAGE_SEPARATOR_CHAR = "."; /** The default package name. */ public static final String DEFAULT_PACKAGE_NAME = "<default>";
/** * Describe the class of an object * * @param object * the object * @return the description */ public static String getDescription(Object object) { StringBuffer buffer = new StringBuffer(); describe(buffer, object); return buffer.toString(); } /** * Describe the class of an object * * @param buffer * the string buffer * @param object * the object */ public static void describe(StringBuffer buffer, Object object) { if (object == null) buffer.append("**null**"); else describe(buffer, object.getClass()); } /** * Describe the class * * @param buffer * the string buffer * @param clazz * the clazz */ public static void describe(StringBuffer buffer, Class clazz) { if (clazz == null) buffer.append("**null**"); else { buffer.append("{class=").append(clazz.getName()); Class[] intfs = clazz.getInterfaces(); if (intfs.length > 0) { buffer.append(" intfs="); for (int i = 0; i < intfs.length; ++i) { buffer.append(intfs[i].getName()); if (i < intfs.length - 1) buffer.append(", "); } } buffer.append("}"); } } /** * Get the short name of the specified class by striping off the package name. * * @param classname * Class name. * @return Short class name. */ public static String stripPackageName(final String classname) { int idx = classname.lastIndexOf(PACKAGE_SEPARATOR); if (idx != -1) return classname.substring(idx + 1, classname.length()); return classname; } /** * Get the short name of the specified class by striping off the package name. * * @param type * Class name. * @return Short class name. */ public static String stripPackageName(final Class type) { return stripPackageName(type.getName()); } /** * Get the package name of the specified class. * * @param classname * Class name. * @return Package name or "" if the classname is in the default * package. * * @throws EmptyStringException * Classname is an empty string. */ public static String getPackageName(final String classname) { if (classname.length() == 0) System.out.println("Empty String Exception"); int index = classname.lastIndexOf(PACKAGE_SEPARATOR); if (index != -1) return classname.substring(0, index); return ""; } /** * Get the package name of the specified class. * * @param type * Class. * @return Package name. */ public static String getPackageName(final Class type) { return getPackageName(type.getName()); }
// /////////////////////////////////////////////////////////////////////// // Primitives // // /////////////////////////////////////////////////////////////////////// /** Primitive type name -> class map. */ private static final Map PRIMITIVE_NAME_TYPE_MAP = new HashMap(); /** Setup the primitives map. */ static { PRIMITIVE_NAME_TYPE_MAP.put("boolean", Boolean.TYPE); PRIMITIVE_NAME_TYPE_MAP.put("byte", Byte.TYPE); PRIMITIVE_NAME_TYPE_MAP.put("char", Character.TYPE); PRIMITIVE_NAME_TYPE_MAP.put("short", Short.TYPE); PRIMITIVE_NAME_TYPE_MAP.put("int", Integer.TYPE); PRIMITIVE_NAME_TYPE_MAP.put("long", Long.TYPE); PRIMITIVE_NAME_TYPE_MAP.put("float", Float.TYPE); PRIMITIVE_NAME_TYPE_MAP.put("double", Double.TYPE); } /** * Get the primitive type for the given primitive name. * * <p> * For example, "boolean" returns Boolean.TYPE and so on... * * @param name * Primitive type name (boolean, int, byte, ...) * @return Primitive type or null. * * @exception IllegalArgumentException * Type is not a primitive class */ public static Class getPrimitiveTypeForName(final String name) { return (Class) PRIMITIVE_NAME_TYPE_MAP.get(name); } /** Map of primitive types to their wrapper classes */ private static final Class[] PRIMITIVE_WRAPPER_MAP = { Boolean.TYPE, Boolean.class, Byte.TYPE, Byte.class, Character.TYPE, Character.class, Double.TYPE, Double.class, Float.TYPE, Float.class, Integer.TYPE, Integer.class, Long.TYPE, Long.class, Short.TYPE, Short.class, }; /** * Get the wrapper class for the given primitive type. * * @param type * Primitive class. * @return Wrapper class for primitive. * * @exception IllegalArgumentException * Type is not a primitive class */ public static Class getPrimitiveWrapper(final Class type) { if (!type.isPrimitive()) { throw new IllegalArgumentException("type is not a primitive class"); } for (int i = 0; i < PRIMITIVE_WRAPPER_MAP.length; i += 2) { if (type.equals(PRIMITIVE_WRAPPER_MAP[i])) return PRIMITIVE_WRAPPER_MAP[i + 1]; } // should never get here, if we do then PRIMITIVE_WRAPPER_MAP // needs to be updated to include the missing mapping System.out.println("Unreachable Statement Exception"); return null; }
/** * Check if the given class is a primitive wrapper class. * * @param type * Class to check. * @return True if the class is a primitive wrapper. */ public static boolean isPrimitiveWrapper(final Class type) { for (int i = 0; i < PRIMITIVE_WRAPPER_MAP.length; i += 2) { if (type.equals(PRIMITIVE_WRAPPER_MAP[i + 1])) { return true; } } return false; } /** * Check if the given class is a primitive class or a primitive wrapper class. * * @param type * Class to check. * @return True if the class is a primitive or primitive wrapper. */ public static boolean isPrimitive(final Class type) { if (type.isPrimitive() || isPrimitiveWrapper(type)) { return true; } return false; } /** * Check type against boolean, byte, char, short, int, long, float, double. * * @param type * The java type name * @return true if this is a primative type name. */ public static boolean isPrimitive(final String type) { return PRIMITIVE_NAME_TYPE_MAP.containsKey(type); }
/** * Instantiate a java class object * * @param expected * the expected class type * @param property * the system property defining the class * @param defaultClassName * the default class name * @return the instantiated object */ public static Object instantiate(Class expected, String property, String defaultClassName) { String className = getProperty(property, defaultClassName); Class clazz = null; try { clazz = loadClass(className); } catch (ClassNotFoundException e) { throw new RuntimeException("Cannot load class " + className, e); } Object result = null; try { result = clazz.newInstance(); } catch (InstantiationException e) { throw new RuntimeException("Error instantiating " + className, e); } catch (IllegalAccessException e) { throw new RuntimeException("Error instantiating " + className, e); } if (expected.isAssignableFrom(clazz) == false) throw new RuntimeException("Class " + className + " from classloader " + clazz.getClassLoader() + " is not of the expected class " + expected + " loaded from " + expected.getClassLoader()); return result; } // /////////////////////////////////////////////////////////////////////// // Class Loading // // /////////////////////////////////////////////////////////////////////// /** * This method acts equivalently to invoking *Thread.currentThread().getContextClassLoader().loadClass(className);
* but it also supports primitive types and array classes of object types or * primitive types. * * @param className * the qualified name of the class or the name of primitive type or * array in the same format as returned by the *java.lang.Class.getName()
method. * @return the Class object for the requested className * * @throws ClassNotFoundException * when theclassLoader
can not find the requested * class */ public static Class loadClass(String className) throws ClassNotFoundException { return loadClass(className, Thread.currentThread().getContextClassLoader()); } /** * This method acts equivalently to invoking classLoader.loadClass(className) * but it also supports primitive types and array classes of object types or * primitive types. * * @param className * the qualified name of the class or the name of primitive type or * array in the same format as returned by the * java.lang.Class.getName() method. * @param classLoader * the ClassLoader used to load classes * @return the Class object for the requested className * * @throws ClassNotFoundException * when theclassLoader
can not find the requested * class */ public static Class loadClass(String className, ClassLoader classLoader) throws ClassNotFoundException { // ClassLoader.loadClass() does not handle primitive types: // // B byte // C char // D double // F float // I int // J long // S short // Z boolean // V void // if (className.length() == 1) { char type = className.charAt(0); if (type == "B") return Byte.TYPE; if (type == "C") return Character.TYPE; if (type == "D") return Double.TYPE; if (type == "F") return Float.TYPE; if (type == "I") return Integer.TYPE; if (type == "J") return Long.TYPE; if (type == "S") return Short.TYPE; if (type == "Z") return Boolean.TYPE; if (type == "V") return Void.TYPE; // else throw... throw new ClassNotFoundException(className); } // Check for a primative type if (isPrimitive(className) == true) return (Class) Classes.PRIMITIVE_NAME_TYPE_MAP.get(className); // Check for the internal vm format: Lclassname; if (className.charAt(0) == "L" && className.charAt(className.length() - 1) == ";") return classLoader.loadClass(className.substring(1, className.length() - 1)); // first try - be optimistic // this will succeed for all non-array classes and array classes that have // already been resolved // try { return classLoader.loadClass(className); } catch (ClassNotFoundException e) { // if it was non-array class then throw it if (className.charAt(0) != "[") throw e; } // we are now resolving array class for the first time // count opening braces int arrayDimension = 0; while (className.charAt(arrayDimension) == "[") arrayDimension++; // resolve component type - use recursion so that we can resolve primitive // types also Class componentType = loadClass(className.substring(arrayDimension), classLoader); // construct array class return Array.newInstance(componentType, new int[arrayDimension]).getClass(); } /** * Get a system property * * @param name * the property name * @param defaultValue * the default value */ private static String getProperty(final String name, final String defaultValue) { return (String) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { return System.getProperty(name, defaultValue); } }); }
}
</source>
Force the given class to be loaded fully.
<source lang="java">
import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.HashSet; import java.util.List; import java.util.Set; /*
* JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */
public class Main {
/** * Force the given class to be loaded fully. * * <p> * This method attempts to locate a static method on the given class the * attempts to invoke it with dummy arguments in the hope that the virtual * machine will prepare the class for the method call and call all of the * static class initializers. * * @param type * Class to force load. * * @throws NullArgumentException * Type is null. */ public static void forceLoad(final Class type) { if (type == null) System.out.println("Null Argument Exception"); // don"t attempt to force primitives to load if (type.isPrimitive()) return; // don"t attempt to force java.* classes to load String packageName = Classes.getPackageName(type); // System.out.println("package name: " + packageName); if (packageName.startsWith("java.") || packageName.startsWith("javax.")) { return; } // System.out.println("forcing class to load: " + type); try { Method methods[] = type.getDeclaredMethods(); Method method = null; for (int i = 0; i < methods.length; i++) { int modifiers = methods[i].getModifiers(); if (Modifier.isStatic(modifiers)) { method = methods[i]; break; } } if (method != null) { method.invoke(null, (Object[]) null); } else { type.newInstance(); } } catch (Exception ignore) { ignore.printStackTrace(); } }
}
</source>
Get a compatible constructor for the given value type
<source lang="java">
import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.security.AccessController; import java.security.CodeSource; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /*
* JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This 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 software 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 software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */
public class Main {
///////////////////////////////////////////////////////////////////////// // Coercion Methods // ///////////////////////////////////////////////////////////////////////// /** * Get a compatible constructor for the given value type * * @param type Class to look for constructor in * @param valueType Argument type for constructor * @return Constructor or null */ public static Constructor getCompatibleConstructor(final Class type, final Class valueType) { // first try and find a constructor with the exact argument type try { return type.getConstructor(new Class[] { valueType }); } catch (Exception ignore) { // if the above failed, then try and find a constructor with // an compatible argument type // get an array of compatible types Class[] types = type.getClasses(); for (int i=0; i<types.length; i++) { try { return type.getConstructor(new Class[] { types[i] }); } catch (Exception ignore2) {} } } // if we get this far, then we can"t find a compatible constructor return null; }
}
</source>
Get the path from where a class is loaded
<source lang="java">
public class Main {
public static void main(String[] args) { Main csl = new Main(); csl.getCodeSourceLocation(); } private void getCodeSourceLocation() { System.out.println("Code source location: " + getClass().getProtectionDomain().getCodeSource().getLocation()); }
}
</source>
Jar Class Loader
<source lang="java">
/*
* Copyright 2002 Sun Microsystems, Inc. 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. * * - Redistribution 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 Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. */
import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.jar.Attributes; import java.util.logging.Level; import java.util.logging.Logger; /**
* A class loader for loading jar files, both local and remote. * Adapted from the Java Tutorial. * * http://java.sun.ru/docs/books/tutorial/jar/api/index.html * * @version 1.3 02/27/02 * @author Mark Davidson */
public class JarClassLoader extends URLClassLoader {
// These manifest attributes were left out of Attributes.Name // They have to go somewhere so the chaces are if you need them, // then you are playing with this class loader. public static final Attributes.Name Attributes_Name_JAVA_BEAN = new Attributes.Name("Java-Bean"); public static final Attributes.Name Attributes_Name_NAME = new Attributes.Name("Name"); private static JarClassLoader loader = null; /** * Null ctor DO NOT USE. This will result in an NPE if the class loader is * used. So this class loader isn"t really Bean like. */ public JarClassLoader() { this(null); } /** * Creates a new JarClassLoader for the specified url. * * @param url The url of the jar file i.e. http://www.xxx.yyy/jarfile.jar * or file:c:\foo\lib\testbeans.jar */ public JarClassLoader(URL url) { super(new URL[] { url }); } /** * Adds the jar file with the following url into the class loader. This can be * a local or network resource. * * @param url The url of the jar file i.e. http://www.xxx.yyy/jarfile.jar * or file:c:\foo\lib\testbeans.jar */ public void addJarFile(URL url) { addURL(url); } /** * Adds a jar file from the filesystems into the jar loader list. * * @param jarfile The full path to the jar file. */ public void addJarFile(String jarfile) { try { URL url = new URL("file:" + jarfile); addURL(url); } catch (IOException ex) { Logger.getAnonymousLogger().log(Level.WARNING, "Error adding jar file", ex); } } // // Static methods for handling the shared instance of the JarClassLoader. // /** * Returns the shared instance of the class loader. */ public static JarClassLoader getJarClassLoader() { return loader; } /** * Sets the static instance of the class loader. */ public static void setJarClassLoader(JarClassLoader cl) { loader = cl; }
}
</source>
Java interpreter replacement
<source lang="java">
/*
* Copyright 2000-2004 The Apache Software Foundation * * 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. * */
import java.lang.reflect.Method; import java.lang.reflect.Modifier; /**
* Java interpreter replacement, i.e., wrapper that uses its own ClassLoader to * modify/generate classes as they"re requested. You can take this as a template * for your own applications.
* Call this wrapper with * * * @version $Id: JavaWrapper.java 386056 2006-03-15 11:31:56Z tcurdt $ * @author * @see ClassLoader */
public class JavaWrapper {
private java.lang.ClassLoader loader; private static java.lang.ClassLoader getClassLoader() { String s = System.getProperty("bcel.classloader"); if ((s == null) || "".equals(s)) { s = "org.apache.bcel.util.ClassLoader"; } try { return (java.lang.ClassLoader) Class.forName(s).newInstance(); } catch (Exception e) { throw new RuntimeException(e.toString()); } } public JavaWrapper(java.lang.ClassLoader loader) { this.loader = loader; } public JavaWrapper() { this(getClassLoader()); } /** * Runs the main method of the given class with the arguments passed in argv * * @param class_name * the fully qualified class name * @param argv * the arguments just as you would pass them directly */ public void runMain(String class_name, String[] argv) throws ClassNotFoundException { Class cl = loader.loadClass(class_name); Method method = null; try { method = cl.getMethod("main", new Class[] { argv.getClass() }); /* * Method main is sane ? */ int m = method.getModifiers(); Class r = method.getReturnType(); if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m) || (r != Void.TYPE)) { throw new NoSuchMethodException(); } } catch (NoSuchMethodException no) { System.out.println("In class " + class_name + ": public static void main(String[] argv) is not defined"); return; } try { method.invoke(null, new Object[] { argv }); } catch (Exception ex) { ex.printStackTrace(); } } /** * Default main method used as wrapper, expects the fully qualified class name * of the real class as the first argument. */ public static void main(String[] argv) throws Exception { /* * Expects class name as first argument, other arguments are by-passed. */ if (argv.length == 0) { System.out.println("Missing class name."); return; } String class_name = argv[0]; String[] new_argv = new String[argv.length - 1]; System.arraycopy(argv, 1, new_argv, 0, new_argv.length); JavaWrapper wrapper = new JavaWrapper(); wrapper.runMain(class_name, new_argv); }
}
</source>
Load Class
<source lang="java">
// $Id: ReflectionHelper.java 16271 2009-04-07 20:20:12Z hardy.ferentschik $ /*
- JBoss, Home of Professional Open Source
- Copyright 2008, Red Hat Middleware LLC, and individual contributors
- by the @authors tag. See the copyright.txt in the distribution for a
- full listing of individual contributors.
- 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.
- /
import java.beans.Introspector; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map;
/**
* Some reflection utility methods. * * @author Hardy Ferentschik */
public class ReflectionHelper {
public static Class<?> loadClass(String name, Class<?> caller) throws ClassNotFoundException { try { //try context classloader, if fails try caller classloader ClassLoader loader = Thread.currentThread().getContextClassLoader(); if ( loader != null ) { return loader.loadClass( name ); } } catch ( ClassNotFoundException e ) { //trying caller classloader if ( caller == null ) { throw e; } } return Class.forName( name, true, caller.getClassLoader() ); }
}
</source>
Load classes
<source lang="java">
/**
* EasyBeans * Copyright (C) 2006 Bull S.A.S. * Contact: easybeans@ow2.org * * 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 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 * * -------------------------------------------------------------------------- * $Id: ClassUtils.java 3783 2008-07-30 13:44:06Z benoitf $ * -------------------------------------------------------------------------- */
/**
* The ClassUtils
class is the central point used to load classes.
* @author Guillaume Sauthier
*/
public final class ClassUtils {
/** * Default constructor. */ private ClassUtils() {} /** * Look up the class in the Tread Context ClassLoader and in the "current" ClassLoader. * @param className The class name to load * @return the corresponding Class instance * @throws ClassNotFoundException if the Class was not found. */ public static Class forName(final String className) throws ClassNotFoundException { // Load classes from different classloaders : // 1. Thread Context ClassLoader // 2. ClassUtils ClassLoader ClassLoader tccl = Thread.currentThread().getContextClassLoader(); Class cls = null; try { // Try with TCCL cls = Class.forName(className, true, tccl); } catch (ClassNotFoundException cnfe) { // Try now with the classloader used to load ClassUtils ClassLoader current = ClassUtils.class.getClassLoader(); try { cls = Class.forName(className, true, current); } catch (ClassNotFoundException cnfe2) { // If this is still unknown, throw an Exception throw cnfe2; } } return cls; } /** * Look up the class in the Tread Context ClassLoader and in the "current" ClassLoader. * @param className The class name to load * @param clazz a class used to get classloader * @return the corresponding Class instance * @throws ClassNotFoundException if the Class was not found. */ public static Class forName(final String className, final Class clazz) throws ClassNotFoundException { // Load classes from different classloaders : // 1. Thread Context ClassLoader // 2. ClassUtils ClassLoader ClassLoader tccl = Thread.currentThread().getContextClassLoader(); Class cls = null; try { // Try with TCCL cls = Class.forName(className, true, tccl); } catch (ClassNotFoundException cnfe) { // Try now with the classloader used to load ClassUtils ClassLoader current = clazz.getClassLoader(); if (current != null) { try { cls = Class.forName(className, true, current); } catch (ClassNotFoundException cnfe2) { // If this is still unknown, throw an Exception throw new ClassNotFoundException("Class Not found in current ThreadClassLoader "" + tccl + "" and in "" + current + "" classloaders.", cnfe2); } } else { // rethrow exception throw cnfe; } } return cls; }
}
</source>
Load class from Thread"s ContextClassLoader, classloader of derived class or the system ClassLoader
<source lang="java">
// // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // 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. //
import java.net.URL; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; /* ------------------------------------------------------------ */ /** ClassLoader Helper.
* This helper class allows classes to be loaded either from the * Thread"s ContextClassLoader, the classloader of the derived class * or the system ClassLoader. ** Usage:
* public class MyClass { * void myMethod() { * ... * Class c=Loader.loadClass(this.getClass(),classname); * ... * } *
* @author Greg Wilkins (gregw) */
public class Loader {
/* ------------------------------------------------------------ */ public static URL getResource(Class loadClass,String name, boolean checkParents) throws ClassNotFoundException { URL url =null; ClassLoader loader=Thread.currentThread().getContextClassLoader(); while (url==null && loader!=null ) { url=loader.getResource(name); loader=(url==null&&checkParents)?loader.getParent():null; } loader=loadClass==null?null:loadClass.getClassLoader(); while (url==null && loader!=null ) { url=loader.getResource(name); loader=(url==null&&checkParents)?loader.getParent():null; } if (url==null) { url=ClassLoader.getSystemResource(name); } return url; } /* ------------------------------------------------------------ */ public static Class loadClass(Class loadClass,String name) throws ClassNotFoundException { return loadClass(loadClass,name,false); } /* ------------------------------------------------------------ */ /** Load a class. * * @param loadClass * @param name * @param checkParents If true, try loading directly from parent classloaders. * @return Class * @throws ClassNotFoundException */ public static Class loadClass(Class loadClass,String name,boolean checkParents) throws ClassNotFoundException { ClassNotFoundException ex=null; Class c =null; ClassLoader loader=Thread.currentThread().getContextClassLoader(); while (c==null && loader!=null ) { try { c=loader.loadClass(name); } catch (ClassNotFoundException e) {if(ex==null)ex=e;} loader=(c==null&&checkParents)?loader.getParent():null; } loader=loadClass==null?null:loadClass.getClassLoader(); while (c==null && loader!=null ) { try { c=loader.loadClass(name); } catch (ClassNotFoundException e) {if(ex==null)ex=e;} loader=(c==null&&checkParents)?loader.getParent():null; } if (c==null) { try { c=Class.forName(name); } catch (ClassNotFoundException e) {if(ex==null)ex=e;} } if (c!=null) return c; throw ex; } public static ResourceBundle getResourceBundle(Class loadClass,String name,boolean checkParents, Locale locale) throws MissingResourceException { MissingResourceException ex=null; ResourceBundle bundle =null; ClassLoader loader=Thread.currentThread().getContextClassLoader(); while (bundle==null && loader!=null ) { try { bundle=ResourceBundle.getBundle(name, locale, loader); } catch (MissingResourceException e) {if(ex==null)ex=e;} loader=(bundle==null&&checkParents)?loader.getParent():null; } loader=loadClass==null?null:loadClass.getClassLoader(); while (bundle==null && loader!=null ) { try { bundle=ResourceBundle.getBundle(name, locale, loader); } catch (MissingResourceException e) {if(ex==null)ex=e;} loader=(bundle==null&&checkParents)?loader.getParent():null; } if (bundle==null) { try { bundle=ResourceBundle.getBundle(name, locale); } catch (MissingResourceException e) {if(ex==null)ex=e;} } if (bundle!=null) return bundle; throw ex; }
}
</source>
Loading a Class That Is Not on the Classpath
<source lang="java">
A URLClassLoader can be used to load classes in any directory. import java.io.File; import java.net.URL; import java.net.URLClassLoader; public class Main {
public static void main(String[] argv) throws Exception { File file = new File("c:\\"); URL url = file.toURI().toURL(); URL[] urls = new URL[] { url }; ClassLoader cl = new URLClassLoader(urls); Class cls = cl.loadClass("com.mycompany.MyClass"); }
}
</source>
Return the context classloader.
<source lang="java">
/*
* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */
import java.net.MalformedURLException; import java.net.URL; /**
* A collection of class management utility methods. * * @version $Id: ClassUtils.java 587751 2007-10-24 02:41:36Z vgritsenko $ */
public class ClassUtils {
/** * Return the context classloader. * BL: if this is command line operation, the classloading issues * are more sane. During servlet execution, we explicitly set * the ClassLoader. * * @return The context classloader. */ public static ClassLoader getClassLoader() { return Thread.currentThread().getContextClassLoader(); }
}
</source>
Unqualified names
<source lang="java">
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Main {
public static void main(String[] argv) throws Exception { Class cls = java.lang.String.class; Method method = cls.getMethods()[0]; Field field = cls.getFields()[0]; Constructor constructor = cls.getConstructors()[0]; String name; name = cls.getName().substring(cls.getPackage().getName().length()+1); System.out.println(name); name = field.getName(); System.out.println(name); name = constructor.getName().substring(cls.getPackage().getName().length()+1); System.out.println(name); name = method.getName(); System.out.println(name); }
} /*String CASE_INSENSITIVE_ORDER String hashCode
- /
</source>
Using the forName() method
<source lang="java">
public class Main {
public static void main(String[] argv) throws Exception { Class cc = null; cc = Class.forName("Main.class"); }
}
</source>
Utility to essentially do Class forName and allow configurable Classloaders.
<source lang="java">
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletResponse; /*
* Copyright 2005 Joe Walker * * 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. */
/**
* @author Joe Walker [joe at getahead dot ltd dot uk] */
public class Main {
/**
* Utility to essentially do Class forName and allow configurable
* Classloaders.
* <p>The initial implementation makes use of the context classloader for
* the current thread.
* @param className The class to create
* @return The class if it is safe or null otherwise.
* @throws ClassNotFoundException If className
is not valid
*/
public static Class<?> classForName(String className) throws ClassNotFoundException
{
// Class.forName(className);
return Thread.currentThread().getContextClassLoader().loadClass(className);
}
}
</source>
Various Class Loader utilities
<source lang="java">
/***
* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Project: www.simpledbm.org * Author : Dibyendu Majumdar * Email : dibyendu@mazumdar.demon.co.uk */
import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Properties;
/**
* Various Class Loader utilities. * @author Dibyendu Majumdar * @since 14.Jan.2005 */
public final class ClassUtils {
private static final String LOG_CLASS_NAME = ClassUtils.class.getName(); /** * Get the ClassLoader to use. We always use the current Thread"s * Context ClassLoader. Assumption is that all threads within the * application share the same ClassLoader. */ private static ClassLoader getClassLoader() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl == null) { throw new NullPointerException(); } return cl; } /** * A wrapper for Class.forName() so that we can change the behaviour * globally without changing the rest of the code. * * @param name Name of the class to be loaded * @throws ClassNotFoundException */ public static Class forName(String name) throws ClassNotFoundException { ClassLoader cl = getClassLoader(); Class clazz = null; clazz = Class.forName(name, true, cl); return clazz; } /** * Load a properties file from the classpath. * * @param name Name of the properties file * @throws IOException If the properties file could not be loaded */ public static InputStream getResourceAsStream(String name) throws IOException { ClassLoader cl = getClassLoader(); InputStream is = null; is = cl.getResourceAsStream(name); if (is == null) { throw new IOException("Unable to load "+ " " + name); } return is; } /** * Load a properties file from the classpath. * * @param name Name of the properties file * @throws IOException If the properties file could not be loaded */ public static Properties getResourceAsProperties(String name) throws IOException { ClassLoader cl = getClassLoader(); InputStream is = null; is = cl.getResourceAsStream(name); if (is == null) { throw new IOException("Unable to load "+ " " + name); } Properties props = new Properties(); props.load(is); return props; } /** * Helper for invoking an instance method that takes a single parameter. * This method also handles parameters of primitive type. * * @param cl * The class that the instance belongs to * @param instance * The object on which we will invoke the method * @param methodName * The method name * @param param * The parameter * @throws Throwable */ public static Object invokeMethod(Class cl, Object instance, String methodName, Object param) throws Throwable { Class paramClass; if (param instanceof Integer) paramClass = Integer.TYPE; else if (param instanceof Long) paramClass = Long.TYPE; else if (param instanceof Short) paramClass = Short.TYPE; else if (param instanceof Boolean) paramClass = Boolean.TYPE; else if (param instanceof Double) paramClass = Double.TYPE; else if (param instanceof Float) paramClass = Float.TYPE; else if (param instanceof Character) paramClass = Character.TYPE; else if (param instanceof Byte) paramClass = Byte.TYPE; else paramClass = param.getClass(); Method method = cl.getMethod(methodName, new Class[] { paramClass }); try { return method.invoke(instance, new Object[] { param }); } catch (InvocationTargetException e) { throw e.getCause(); } } /** * Helper for invoking a static method that takes one parameter. * * @param cl * The class that implements the static method * @param methodName * The method name * @param param * A parameter * @param paramClass * Class of the parameter * @throws Throwable */ public static Object invokeStaticMethod(Class cl, String methodName, Object param, Class paramClass) throws Throwable { Method method = cl.getMethod(methodName, new Class[] { paramClass }); try { return method.invoke(null, new Object[] { param }); } catch (InvocationTargetException e) { throw e.getCause(); } } /** * Helper for invoking a constructor with one parameter. * * @param className Class of which an instance is to be allocated * @param param Parameter * @param paramClass Type of the parameter * @throws ClassNotFoundException * @throws SecurityException * @throws NoSuchMethodException * @throws IllegalArgumentException * @throws InstantiationException * @throws IllegalAccessException * @throws InvocationTargetException */ public static Object createObject(String className, Object param, Class paramClass) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { Class clazzImpl = ClassUtils.forName(className); Constructor ctor = clazzImpl .getConstructor(new Class[] { paramClass }); Object instance = ctor.newInstance(new Object[] { param }); return instance; }
}
</source>
Zip Class Loader
<source lang="java">
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.LinkedList; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class ZipClassLoader extends ClassLoader {
// This code was posted on a forum by "leukbr" on March 30, 2001. // http://forums.sun.ru/thread.jspa?threadID=360060&forumID=31 // I"ve modified it substantially to include a thread that keeps the file // open for OPEN_TIME milliseconds so time isn"t wasted continually // opening and closing the file. private static final int OPEN_TIME = 5000; private static final int DEBUG = 0; // 0 = no debug messages // 1 = open/close ZIP file only // 2 = also each resource request // 3 = all messages while retrieving resource private static final int REQUEST_FIND = 0; private static final int REQUEST_LOAD = 1; private static class Request { int action; String resource; boolean responseSent; Object response; Request(int action, String resource) { this.action = action; this.resource = resource; this.responseSent = false; } public String toString() { String act = action == REQUEST_LOAD ? "load" : action == REQUEST_FIND ? "find" : "act" + action; return act + ":" + resource; } void setResponse(Object value) { synchronized(this) { response = value; responseSent = true; notifyAll(); } } void ensureDone() { boolean aborted = false; synchronized(this) { if(!responseSent) { aborted = true; responseSent = true; response = null; notifyAll(); } } if(aborted && DEBUG >= 1) { System.err.println("request not handled successfully"); //OK } } Object getResponse() { synchronized(this) { while(!responseSent) { try { this.wait(1000); } catch(InterruptedException e) { } } return response; } } } private class WorkThread extends Thread { private LinkedList requests = new LinkedList(); private ZipFile zipFile = null; public void run() { try { while(true) { Request request = waitForNextRequest(); if(request == null) return; if(DEBUG >= 2) System.err.println("processing " + request); //OK try { switch(request.action) { case REQUEST_LOAD: performLoad(request); break; case REQUEST_FIND: performFind(request); break; } } finally { request.ensureDone(); } if(DEBUG >= 2) System.err.println("processed: " + request.getResponse()); //OK } } catch(Throwable t) { if(DEBUG >= 3) { System.err.print("uncaught: "); t.printStackTrace(); } //OK } finally { if(zipFile != null) { try { zipFile.close(); zipFile = null; if(DEBUG >= 1) System.err.println(" ZIP closed"); //OK } catch(IOException e) { if(DEBUG >= 1) System.err.println("Error closing ZIP file"); //OK } } } } private Request waitForNextRequest() { synchronized(bgLock) { long start = System.currentTimeMillis(); while(requests.isEmpty()) { long elapse = System.currentTimeMillis() - start; if(elapse >= OPEN_TIME) { bgThread = null; return null; } try { bgLock.wait(OPEN_TIME); } catch(InterruptedException e) { } } return (Request) requests.removeFirst(); } } private void performFind(Request req) { ensureZipOpen(); Object ret = null; try { if(zipFile != null) { if(DEBUG >= 3) System.err.println(" retrieve ZIP entry"); //OK String res = req.resource; ZipEntry zipEntry = zipFile.getEntry(res); if(zipEntry != null) { String url = "jar:" + zipPath.toURI() + "!/" + res; ret = new URL(url); if(DEBUG >= 3) System.err.println(" found: " + url); //OK } } } catch(Throwable ex) { if(DEBUG >= 3) System.err.println(" error retrieving data"); //OK ex.printStackTrace(); } req.setResponse(ret); } private void performLoad(Request req) { BufferedInputStream bis = null; ensureZipOpen(); Object ret = null; try { if(zipFile != null) { if(DEBUG >= 3) System.err.println(" retrieve ZIP entry"); //OK ZipEntry zipEntry = zipFile.getEntry(req.resource); if(zipEntry != null) { if(DEBUG >= 3) System.err.println(" load file"); //OK byte[] result = new byte[(int) zipEntry.getSize()]; bis = new BufferedInputStream(zipFile.getInputStream(zipEntry)); try { bis.read(result, 0, result.length); ret = result; } catch(IOException e) { if(DEBUG >= 3) System.err.println(" error loading file"); //OK } } } } catch(Throwable ex) { if(DEBUG >= 3) System.err.println(" error retrieving data"); //OK ex.printStackTrace(); } finally { if (bis!=null) { try { if(DEBUG >= 3) System.err.println(" close file"); //OK bis.close(); } catch (IOException ioex) { if(DEBUG >= 3) System.err.println(" error closing data"); //OK } } } req.setResponse(ret); } private void ensureZipOpen() { if(zipFile == null) { try { if(DEBUG >= 3) System.err.println(" open ZIP file"); //OK zipFile = new ZipFile(zipPath); if(DEBUG >= 1) System.err.println(" ZIP opened"); //OK } catch(IOException e) { if(DEBUG >= 1) System.err.println(" error opening ZIP file"); //OK } } } } private File zipPath; private HashMap classes = new HashMap(); private Object bgLock = new Object(); private WorkThread bgThread = null; public ZipClassLoader(String zipFileName) { this(new File(zipFileName)); } public ZipClassLoader(File zipFile) { zipPath = zipFile; } public URL findResource(String resourceName) { if(DEBUG >= 3) System.err.println("findResource " + resourceName); //OK Object ret = request(REQUEST_FIND, resourceName); if(ret instanceof URL) { return (URL) ret; } else { return super.findResource(resourceName); } } public Class findClass(String className) throws ClassNotFoundException { boolean found = false; Object result = null; // check whether we have loaded this class before synchronized(classes) { found = classes.containsKey(className); if(found) result = classes.get(className); } // try loading it from the ZIP file if we haven"t if(!found) { String resourceName = className.replace(".", "/") + ".class"; result = request(REQUEST_LOAD, resourceName); if(result instanceof byte[]) { if(DEBUG >= 3) System.err.println(" define class"); //OK byte[] data = (byte[]) result; result = defineClass(className, data, 0, data.length); if(result != null) { if(DEBUG >= 3) System.err.println(" class defined"); //OK } else { if(DEBUG >= 3) System.err.println(" format error"); //OK result = new ClassFormatError(className); } } synchronized(classes) { classes.put(className, result); } } if(result instanceof Class) { return (Class) result; } else if(result instanceof ClassNotFoundException) { throw (ClassNotFoundException) result; } else if(result instanceof Error) { throw (Error) result; } else { return super.findClass(className); } } private Object request(int action, String resourceName) { Request request; synchronized(bgLock) { if(bgThread == null) { // start the thread if it isn"t working bgThread = new WorkThread(); bgThread.start(); } request = new Request(action, resourceName); bgThread.requests.addLast(request); bgLock.notifyAll(); } return request.getResponse(); }
}
</source>