AppClassLoader,ExtClassLoaderとURLClassLoaderの関係を分析する
AppClassLoader,ExtClassLoaderとURLClassLoaderの関係を分析する
テストコード:
結論:
1.ユーザーがカスタマイズしたクラスはアプリケーション(システム)クラスローダAppClassLoaderによってロードされる
2.「親父委託メカニズム」において、拡張クラスローダExtClassLoaderはAppClassLoaderの親父である.
3.AppClassLoaderとExtClassLoaderは共にURLClassLoaderローダに拡張する.
4.ExtClassLoaderを継承する代わりにAppClassLoaderも説明する.
継承関係:
java.lang.Object
--- java.lang.ClassLoader --- java.security.SecureClassLoader --- java.net.URLClassLoader --- sun.misc.Launcher$ExtClassLoader
java.lang.Object
--- java.lang.ClassLoader --- java.security.SecureClassLoader --- java.net.URLClassLoader --- sun.misc.Launcher$AppClassLoader
実はとても简単で、直接AppClassLoaderのソースコードを见てもいいですか、ははは、やっと良い东を见つけて、上
JDK7: http://download.java.net/openjdk/jdk7/
JDK6: http://download.java.net/openjdk/jdk6/
ソースコードをダウンロードすればいいです
ソースコードを直接見てみましょう.
ああ、AppClassLoaderのソースコードを見て、わかりましたね.AppClassLoaderはURLClassLoaderを継承しています.そして、コンストラクション関数はURLClassLoaderを直接呼び出す構造です.
関数,loadClass(String name,boolean resolve)メソッドはパケットのセキュリティチェックを簡単にしただけで,ClassLoaderのloadClass(String name,boolean resolve)メソッドを呼び出すことになるが,その他にも差は少ない.だからその機能はURLClassLoaderとあまり差がありません...
ExtClassLoaderでも差が少ないので、ソースコードを見てみましょう.
テストコード:
class Hello
{
public String str = "Hello World";
public void fun()
{
System.out.println(str);
}
}
public class Test
{
public static void main(String[] args)
{
Hello hello = new Hello();
hello.fun();
System.out.println("----------------------");
//Hello
ClassLoader classLoaderOfHello = Hello.class.getClassLoader();
System.out.println("Hello is Loaded by : "+classLoaderOfHello);
System.out.println("----------------------");
//Hello Class
Class AppClazz = classLoaderOfHello.getClass();
// Hello Class
while(AppClazz != null)
{
System.out.println(AppClazz);
AppClazz = AppClazz.getSuperclass();
}
System.out.println("----------------------");
// Class
Class ExtClazz = classLoaderOfHello.getParent().getClass();
while(ExtClazz != null)
{
System.out.println(ExtClazz);
ExtClazz = ExtClazz.getSuperclass();
}
}
}
結論:
1.ユーザーがカスタマイズしたクラスはアプリケーション(システム)クラスローダAppClassLoaderによってロードされる
2.「親父委託メカニズム」において、拡張クラスローダExtClassLoaderはAppClassLoaderの親父である.
3.AppClassLoaderとExtClassLoaderは共にURLClassLoaderローダに拡張する.
4.ExtClassLoaderを継承する代わりにAppClassLoaderも説明する.
継承関係:
java.lang.Object
--- java.lang.ClassLoader --- java.security.SecureClassLoader --- java.net.URLClassLoader --- sun.misc.Launcher$ExtClassLoader
java.lang.Object
--- java.lang.ClassLoader --- java.security.SecureClassLoader --- java.net.URLClassLoader --- sun.misc.Launcher$AppClassLoader
実はとても简単で、直接AppClassLoaderのソースコードを见てもいいですか、ははは、やっと良い东を见つけて、上
JDK7: http://download.java.net/openjdk/jdk7/
JDK6: http://download.java.net/openjdk/jdk6/
ソースコードをダウンロードすればいいです
ソースコードを直接見てみましょう.
/**
* The class loader used for loading from java.class.path.
* runs in a restricted security context.
*/
static class AppClassLoader extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
public static ClassLoader getAppClassLoader(final ClassLoader extcl)
throws IOException
{
final String s = System.getProperty("java.class.path");
final File[] path = (s == null) ? new File[0] : getClassPath(s);
return AccessController.doPrivileged(
new PrivilegedAction<AppClassLoader>() {
public AppClassLoader run() {
URL[] urls =
(s == null) ? new URL[0] : pathToURLs(path);
return new AppClassLoader(urls, extcl);
}
});
}
/*
* Creates a new AppClassLoader
*/
AppClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent, factory);
}
/**
* Override loadClass so we can checkPackageAccess.
*/
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
int i = name.lastIndexOf('.');
if (i != -1) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPackageAccess(name.substring(0, i));
}
}
return (super.loadClass(name, resolve));
}
/**
* allow any classes loaded from classpath to exit the VM.
*/
protected PermissionCollection getPermissions(CodeSource codesource)
{
PermissionCollection perms = super.getPermissions(codesource);
perms.add(new RuntimePermission("exitVM"));
return perms;
}
/**
* This class loader supports dynamic additions to the class path
* at runtime.
*
* @see java.lang.instrument.Instrumentation#appendToSystemClassPathSearch
*/
private void appendToClassPathForInstrumentation(String path) {
assert(Thread.holdsLock(this));
// addURL is a no-op if path already contains the URL
super.addURL( getFileURL(new File(path)) );
}
/**
* create a context that can read any directories (recursively)
* mentioned in the class path. In the case of a jar, it has to
* be the directory containing the jar, not just the jar, as jar
* files might refer to other jar files.
*/
private static AccessControlContext getContext(File[] cp)
throws java.net.MalformedURLException
{
PathPermissions perms =
new PathPermissions(cp);
ProtectionDomain domain =
new ProtectionDomain(new CodeSource(perms.getCodeBase(),
(java.security.cert.Certificate[]) null),
perms);
AccessControlContext acc =
new AccessControlContext(new ProtectionDomain[] { domain });
return acc;
}
}
ああ、AppClassLoaderのソースコードを見て、わかりましたね.AppClassLoaderはURLClassLoaderを継承しています.そして、コンストラクション関数はURLClassLoaderを直接呼び出す構造です.
関数,loadClass(String name,boolean resolve)メソッドはパケットのセキュリティチェックを簡単にしただけで,ClassLoaderのloadClass(String name,boolean resolve)メソッドを呼び出すことになるが,その他にも差は少ない.だからその機能はURLClassLoaderとあまり差がありません...
ExtClassLoaderでも差が少ないので、ソースコードを見てみましょう.
/*
* Creates a new ExtClassLoader for the specified directories.
*/
public ExtClassLoader(File[] dirs) throws IOException {
super(getExtURLs(dirs), null, factory);
}
private static File[] getExtDirs() {
String s = System.getProperty("java.ext.dirs");
File[] dirs;
if (s != null) {
StringTokenizer st =
new StringTokenizer(s, File.pathSeparator);
int count = st.countTokens();
dirs = new File[count];
for (int i = 0; i < count; i++) {
dirs[i] = new File(st.nextToken());
}
} else {
dirs = new File[0];
}
return dirs;
}
private static URL[] getExtURLs(File[] dirs) throws IOException {
Vector<URL> urls = new Vector<URL>();
for (int i = 0; i < dirs.length; i++) {
String[] files = dirs[i].list();
if (files != null) {
for (int j = 0; j < files.length; j++) {
if (!files[j].equals("meta-index")) {
File f = new File(dirs[i], files[j]);
urls.add(getFileURL(f));
}
}
}
}
URL[] ua = new URL[urls.size()];
urls.copyInto(ua);
return ua;
}
/*
* Searches the installed extension directories for the specified
* library name. For each extension directory, we first look for
* the native library in the subdirectory whose name is the value
* of the system property <code>os.arch</code>. Failing that, we
* look in the extension directory itself.
*/
public String findLibrary(String name) {
name = System.mapLibraryName(name);
URL[] urls = super.getURLs();
File prevDir = null;
for (int i = 0; i < urls.length; i++) {
// Get the ext directory from the URL
File dir = new File(urls[i].getPath()).getParentFile();
if (dir != null && !dir.equals(prevDir)) {
// Look in architecture-specific subdirectory first
// Read from the saved system properties to avoid deadlock
String arch = VM.getSavedProperty("os.arch");
if (arch != null) {
File file = new File(new File(dir, arch), name);
if (file.exists()) {
return file.getAbsolutePath();
}
}
// Then check the extension directory
File file = new File(dir, name);
if (file.exists()) {
return file.getAbsolutePath();
}
}
prevDir = dir;
}
return null;
}
private static AccessControlContext getContext(File[] dirs)
throws IOException
{
PathPermissions perms =
new PathPermissions(dirs);
ProtectionDomain domain = new ProtectionDomain(
new CodeSource(perms.getCodeBase(),
(java.security.cert.Certificate[]) null),
perms);
AccessControlContext acc =
new AccessControlContext(new ProtectionDomain[] { domain });
return acc;
}
}