|
Glassfish example source code file (ClassLoaderUtil.java)
The Glassfish ClassLoaderUtil.java source code
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.appserv;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;
import java.util.Vector;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.text.MessageFormat;
import sun.misc.URLClassPath;
import com.sun.logging.LogDomains;
/**
* Provides utility functions related to URLClassLoaders or subclasses of it.
*
* W A R N I N G
*
*This class uses undocumented, unpublished, private data structures inside
*java.net.URLClassLoader and sun.misc.URLClassPath. Use with extreme caution.
*
* @author tjquinn
*/
public class ClassLoaderUtil {
/** records whether initialization has been completed */
private static boolean isInitialized = false;
/** names of classes and fields of interest for closing the loader's jar files */
private static final String URLCLASSLOADER_UCP_FIELD_NAME = "ucp";
private static final String URLCLASSPATH_LOADERS_FIELD_NAME = "loaders"; // ArrayList of URLClassPath.Loader
private static final String URLCLASSPATH_URLS_FIELD_NAME = "urls"; // Stack of URL
private static final String URLCLASSPATH_LMAP_FIELD_NAME = "lmap"; // HashMap of String -> URLClassPath.Loader
private static final String URLCLASSPATH_JARLOADER_INNER_CLASS_NAME = "sun.misc.URLClassPath$JarLoader";
private static final String URLCLASSPATH_JARLOADER_JARFILE_FIELD_NAME = "jar";
/* Fields used during processing - they can be set up once and then used repeatedly */
private static Field jcpField;
private static Field loadersField;
private static Field urlsField;
private static Field lmapField;
private static Class jarLoaderInnerClass;
private static Field jarFileField;
private static boolean initDone = false;
/**
*Initializes the class.
*<p>
*Each utility method should invoke init() before doing their own work
*to make sure the initialization is done.
*@throws any Throwable detected during static init.
*/
private static void init() throws Throwable {
if ( ! initDone) {
initForClosingJars();
initDone = true;
}
}
/**
*Sets up variables used in closing a loader's jar files.
*@throws NoSuchFieldException in case a field of interest is not found where expected
*/
private static void initForClosingJars() throws NoSuchFieldException {
jcpField = getField(URLClassLoader.class, URLCLASSLOADER_UCP_FIELD_NAME);
loadersField = getField(URLClassPath.class, URLCLASSPATH_LOADERS_FIELD_NAME);
urlsField = getField(URLClassPath.class, URLCLASSPATH_URLS_FIELD_NAME);
lmapField = getField(URLClassPath.class, URLCLASSPATH_LMAP_FIELD_NAME);
jarLoaderInnerClass = getInnerClass(URLClassPath.class, URLCLASSPATH_JARLOADER_INNER_CLASS_NAME);
jarFileField = getField(jarLoaderInnerClass, URLCLASSPATH_JARLOADER_JARFILE_FIELD_NAME);
}
/**
*Retrieves a Field object for a given field on the specified class, having
*set it accessible.
*@param cls the Class on which the field is expected to be defined
*@param fieldName the name of the field of interest
*@throws NoSuchFieldException in case of any error retriving information about the field
*/
private static Field getField(Class cls, String fieldName) throws NoSuchFieldException {
try {
Field field = cls.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException nsfe) {
NoSuchFieldException e = new NoSuchFieldException(getMessage("classloaderutil.errorGettingField", fieldName));
e.initCause(nsfe);
throw e;
}
}
/**
*Retrieves a given inner class definition from the specified outer class.
*@param cls the outer Class
*@param innerClassName the fully-qualified name of the inner class of interest
*/
private static Class getInnerClass(Class cls, String innerClassName) {
Class result = null;
Class[] innerClasses = cls.getDeclaredClasses();
for (Class c : innerClasses) {
if (c.getName().equals(innerClassName)) {
result = c;
break;
}
}
return result;
}
/**
*Releases resources held by the URLClassLoader. Notably, close the jars
*opened by the loader. This does not prevent the class loader from
*continuing to return classes it has already resolved.
*@param classLoader the instance of URLClassLoader (or a subclass)
*@return array of IOExceptions reporting jars that failed to close
*/
public static void releaseLoader(URLClassLoader classLoader) {
releaseLoader(classLoader, null);
}
/**
*Releases resources held by the URLClassLoader. Notably, close the jars
*opened by the loader. This does not prevent the class loader from
*continuing to return classes it has alrady resolved although that is not
*what we intend to happen. Initializes and updates the Vector of
*jars that have been successfully closed.
*<p>
*Any errors are logged.
*@param classLoader the instance of URLClassLoader (or a subclass)
*@param jarsClosed a Vector of Strings that will contain the names of jars
* successfully closed; can be null if the caller does not need the information returned
*@return array of IOExceptions reporting jars that failed to close; null
*indicates that an error other than an IOException occurred attempting to
*release the loader; empty indicates a successful release; non-empty
*indicates at least one error attempting to close an open jar.
*/
public static IOException [] releaseLoader(URLClassLoader classLoader, Vector<String> jarsClosed) {
IOException[] result = null;
try {
init();
/* Records all IOExceptions thrown while closing jar files. */
Vector<IOException> ioExceptions = new Vector
Other Glassfish examples (source code examples)Here is a short list of links related to this Glassfish ClassLoaderUtil.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.