ClassLoaderについて
3411 ワード
java.lang public abstract class ClassLoader
classのロードは、委任モデル(delegation model)によって行われます.各クラス・ローダには、関連する親クラス・ローダがあります.クラスをロードすると、class Loaderはそのparent class loaderにクラスをロードするように委任されます.仮想マシン内に構築されたclass Loaderはbootstrap class loaderと呼ばれ、親ローダはありません.
配列class(array classes)はクラスローダによって作成されるのではなく、Javaランタイム(Java runtime)によって必要に応じて自動的に作成されます.
ClassLoaderは、まずlocateでclassのbytecodeを指定し、クラスのbytecodeを実行時のClassに変換します.ランタイムシステムは、bootstrap classes、extension classes、user classesをロードするclass loaderをそれぞれ提供します.CLASSSPATH環境変数は、実行時にシステムがbytecodeをロードする場所を示す.
クラス・ローダは、クラスが要求されると、まずこのクラスが以前にロードされたかどうかを確認します.そうでない場合、親ローダにこのクラスをロードするように要求します.親ローダがこのclassを見つけられなかった場合、クラスローダは自分でこのclassをロードしようとする.
マルチスレッド環境では、カスタムクラスローダで循環委任モデルの問題が発生し、デッドロックが発生する可能性があります.
ClassをロードするとClassLoaderオブジェクト全体が同期し、デッドロックになる可能性があります
JDK1.7 parallel capable class loaderを導入し、ロックの粒度がclassLoaderから(classLoader+className)に変わり、ロックの粒度を縮小し、この問題を解決しました.
ClassLoaderは初期化時にregisterAsParallelCapable()メソッドを呼び出すことで自分をParallel capable class loaderとして登録し、classを同時ロードすることができ、システム性能の向上に役立つ.デフォルトではClassLoaderはParallel Capableに登録されています
付JDK 1.8クラスClassLoaderのloadClass()メソッド:
参照リソース:1.JDK 8 ClassLoaderソース2.http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html
classのロードは、委任モデル(delegation model)によって行われます.各クラス・ローダには、関連する親クラス・ローダがあります.クラスをロードすると、class Loaderはそのparent class loaderにクラスをロードするように委任されます.仮想マシン内に構築されたclass Loaderはbootstrap class loaderと呼ばれ、親ローダはありません.
配列class(array classes)はクラスローダによって作成されるのではなく、Javaランタイム(Java runtime)によって必要に応じて自動的に作成されます.
ClassLoaderは、まずlocateでclassのbytecodeを指定し、クラスのbytecodeを実行時のClassに変換します.ランタイムシステムは、bootstrap classes、extension classes、user classesをロードするclass loaderをそれぞれ提供します.CLASSSPATH環境変数は、実行時にシステムがbytecodeをロードする場所を示す.
クラス・ローダは、クラスが要求されると、まずこのクラスが以前にロードされたかどうかを確認します.そうでない場合、親ローダにこのクラスをロードするように要求します.親ローダがこのclassを見つけられなかった場合、クラスローダは自分でこのclassをロードしようとする.
マルチスレッド環境では、カスタムクラスローダで循環委任モデルの問題が発生し、デッドロックが発生する可能性があります.
Class Hierarchy:
class A extends B
class C extends D
ClassLoader Delegation Hierarchy:
Custom Classloader CL1:
directly loads class A
delegates to custom ClassLoader CL2 for class B
Custom Classloader CL2:
directly loads class C
delegates to custom ClassLoader CL1 for class D
Thread 1:
Use CL1 to load class A (locks CL1)
defineClass A triggers
loadClass B (try to lock CL2)
Thread 2:
Use CL2 to load class C (locks CL2)
defineClass C triggers
loadClass D (try to lock CL1)
ClassをロードするとClassLoaderオブジェクト全体が同期し、デッドロックになる可能性があります
JDK1.7 parallel capable class loaderを導入し、ロックの粒度がclassLoaderから(classLoader+className)に変わり、ロックの粒度を縮小し、この問題を解決しました.
Thread 1:
Use CL1 to load class A (locks CL1+A)
defineClass A triggers
loadClass B (locks CL2+B)
Thread 2:
Use CL2 to load class C (locks CL2+C)
defineClass C triggers
loadClass D (locks CL1+D)
ClassLoaderは初期化時にregisterAsParallelCapable()メソッドを呼び出すことで自分をParallel capable class loaderとして登録し、classを同時ロードすることができ、システム性能の向上に役立つ.デフォルトではClassLoaderはParallel Capableに登録されています
付JDK 1.8クラスClassLoaderのloadClass()メソッド:
protected Class> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
参照リソース:1.JDK 8 ClassLoaderソース2.http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html