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
/*
* 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.
*
*<br>The classloaders in the searchlist are of two types: <b>shared</b> and
* <b>non-shared</b>. A shared classloader may be in use by other code, and
* so <i>no</i> duplicates should be made of the classes in the loaders.
*<br>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).
*
*<br>The SearchlistClassLoader API therefore makes a clear distinction
* between <b>shared</b> and <b>non-shared</b> classloaders.
*<br>The {@link #add(ClassLoader)} method adds an <i>existing</i> classloader
* which means the added classloader is treated as being <i>shared</i>.
*<br>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 <i>non-shared</i>.
*<br>
*
*<br>SearchlistClassLoader therefore also allows control over the order in
* which classloaders are searched, through the {@link #setSearchMode(byte)}
* method.
*
*<br>The possible <i>searchmodes</i> are:
*<ul>
* <li>SHARED
* <br>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.
*
* <li>NONSHARED
* <br>added URLs are searched <i>before</i> 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.
*
* <li>ORDERED
* <br>added classloaders and URLs are searched in the order in which
* they were added to the searchlist.
*</ul>
*
*<br>There is also a method which retrieves a class <i>without</i> searching
* any added classloaders. This effectively retrieves the <i>canonical</i>
* instance of the requested class (see {@link #loadLocalClass(String)}
* and {@link #getLocalResource(String)}).
*
*<p><i>Implementation notes:</i>.
*
*<br>Because each class object is associated with the classloader which
* defined it (see ClassLoader.defineClass(...)), SearchlistClassLoader
* must associate <i>itself</i> with <i>all</i> class objects it loads
* through <i>non-shared</i> loaders, and similarly <i>must not</i> associate
* itself with class objects loaded through shared loaders.
* (See {@link #findClass(String)}.)
*
*<br>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 <i>name</i>.
*
*<br>This does <i>not</i> search the searchlist. Only classes loaded
* directly by this loader or its parent are returned.
*
*<br>This method can be used to retrieve the <i>canonical</i> 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 <i>name</i>.
*
*<br>This does <i>not</i> search the searchlist. Only resources loaded
* directly by this loader or its parent are returned.
*
*<br>This method can be used to retrieve the <i>canonical</i> 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 <i>null</i>.
*/
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.
*
*<br>This method is called by inherited loadClass() methods whenever
* a class cannot be found in the parent classloader.
*
*<br>If the class is found using a <i>shared</i> loader, then it is
* returned directly. If the class is found using a <i>non-shared</i>
* 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)
*
* <em>Note</em>Inherited behaviour of loadClass() and getResource() means
* that this method is <em>not</em> 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 <i>null</i> 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 <i>null</i>
* 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 <i>null</i>.
*/
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 <i>null</i>
*/
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 <i>null</i>
*/
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.
*
*<pre>
* Eg: translate("the dog.", "o.", "i")
* returns "the dig", because "o" is replaced with "i", and "." is
* replaced with nothing (ie deleted).
*</pre>
*
* @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;
}
}
}
A class to simplify access to resources through the classloader
/*
* 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;
}
}
Analyze ClassLoader hierarchy for any given object or class loader
/*
* 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);
}
}
Class Finder
/*
* 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 <em>not</em> 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 <tt>Class</tt> 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:
* <ol>
* <li>The loader that loaded the class or instance referred to in the API
* that caused this class to be loaded (the context class).</li>
* <li>The loader returned in the current context by
* <tt>Thread.getContextClassLoader()</tt>.</li>
* <li>The loader returned by <tt>Thread.getContextClassLoader()</tt> at
* the time this <tt>ClassFinder</tt> was constructed (which should equate
* to the time of <tt>PersistenceManagerFactory.getPersistenceManager()</tt>).
* </li>
* </ol>
*
* @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 <code>null</code> 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 <tt>Class</tt> object associated with the class or interface
* with the given string name.
* <p>
* This method is equivalent to:
* <blockquote><pre>
* classForName(className, initialize, null)
* </pre></blockquote>
*
* @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 <tt>Class</tt> 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 <em>not</em>
* 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 <tt>ClassFinder</tt> objects are considered equal if their original
* context class loaders are all equal.
*
* @param obj
* the reference object with which to compare
*
* @return
* <tt>true</tt> if this object is equal to the obj argument;
* <tt>false</tt> 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);
}
}
Class For Name
// $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() );
}
}
Context ClassLoader
/**************************************************************************************
* 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 a <code>Class</code> 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 a <code>URL</code> 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 <code>InputStream</code> 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;
}
}
Determining from Where a Class Was Loaded
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 {
}
}
does Class Exist
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;
}
}
Dynamically Reloading a Modified Class
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();
}
}
Equivalently to invoking Thread.currentThread().getContextClassLoader().loadClass(className); but it supports primitive types and array classes of object types or primitive types.
/*
* 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 <code>Class</code> utilities.
*
* @version <tt>$Revision: 2787 $</tt>
* @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 <i>default</i>
* 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
* <code>Thread.currentThread().getContextClassLoader().loadClass(className);</code>
* 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
* <code>java.lang.Class.getName()</code> method.
* @return the Class object for the requested className
*
* @throws ClassNotFoundException
* when the <code>classLoader</code> 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 the <code>classLoader</code> 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);
}
});
}
}
Force the given class to be loaded fully.
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 <i>null</i>.
*/
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();
}
}
}
Get a compatible constructor for the given value type
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;
}
}
Get the path from where a class is loaded
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());
}
}
Jar Class Loader
/*
* 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;
}
}
Java interpreter replacement
/*
* 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.<br>
* 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);
}
}
Load Class
// $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() );
}
}
Load classes
/**
* 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 <code>ClassUtils</code> 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;
}
}
Load class from Thread"s ContextClassLoader, classloader of derived class or the system ClassLoader
//
// 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.
*
* <B>Usage:</B><PRE>
* public class MyClass {
* void myMethod() {
* ...
* Class c=Loader.loadClass(this.getClass(),classname);
* ...
* }
* </PRE>
* @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;
}
}
Loading a Class That Is Not on the Classpath
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");
}
}
Return the context classloader.
/*
* 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();
}
}
Unqualified names
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
*/
Using the forName() method
public class Main {
public static void main(String[] argv) throws Exception {
Class cc = null;
cc = Class.forName("Main.class");
}
}
Utility to essentially do Class forName and allow configurable Classloaders.
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 <code>className</code> is not valid
*/
public static Class<?> classForName(String className) throws ClassNotFoundException
{
// Class.forName(className);
return Thread.currentThread().getContextClassLoader().loadClass(className);
}
}
Various Class Loader utilities
/***
* 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;
}
}
Zip Class Loader
/* 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();
}
}