クラスローダーの分類
ロードのしくみ
mainメソッドはなぜ動く
JDBCドライバの怪
java9 jigsaw
Native Code
${JAVA_HOME}/jre/lib/
rt.jar
標準クラスライブラリIt is also known as application class loader
ご存知クラスパスからクラスをロード
java.net.URLClassLoaderのサブクラス
親から順番に探すため、親子で同一クラスを別々にロードは基本的に出来ない
URL jarUrl = new File(jarPath).toURI().toURL();
URLClassLoader cl =
URLClassLoader.newInstance(new URL[]{jarUrl});
Class<?> clazz = cl.loadClass("java.lang.String");
clazz.getClassLoader(); =====> null
Bootstrap Class Loaderでロードされたクラスは、
getClassLoader()の戻りが null になる
package com.company;
public class Singleton {
private Singleton(){}
public static final Singleton INSTANCE = new Singleton();
}
親の検索対象とならないよう起動時のクラスパスからは外しておき、実行時に検索
URL[] urls = { new File("out/production/singleton/").toURI().toURL() };
ClassLoader cl1 = URLClassLoader.newInstance(urls);
ClassLoader cl2 = URLClassLoader.newInstance(urls);
Object instance1
= cl1.loadClass("com.company.Singleton").getField("INSTANCE").get(null);
Object instance2
= cl2.loadClass("com.company.Singleton").getField("INSTANCE").get(null);
System.out.println(instance1.getClass());
System.out.println(instance2.getClass());
System.out.println(instance1 == instance2);
System.out.println(instance1.getClass().equals(instance2.getClass()));
class com.company.Singleton
class com.company.Singleton
false
false
protected Class<?>
defineClass(String name,
byte[] b,
int off,
int len)
findClassメソッドは、.classファイルをbyte[]に格納後、このメソッドへ渡す
これら全て、defineClassを呼んでいる
バイト配列を直接読込む検証もやってみたい
public static Class<?> checkAndLoadMain(boolean printToStderr, int mode, String what)
static void validateMainClass(Class<?> mainClass)
mainClass.getMethod("main", String[].class)
mainClass は起動引数で指定されたクラスを ClassLoader.findClassで検索したもの
おなじみ?Reflectionで探している
public enum LauncherHelper {
INSTANCE;
// 以下、全て staticメンバ
checkAndLoadMainはJNI経由でCから呼ばれる
Utility的なクラス
public final class LauncherHelper {
// No instantiation
private LauncherHelper() {}
java9のブランチでは普通にclass...
リファクタ?
以前、JDBCの話をした時に、JDBC Ver.4以降であれば
Class.forName("com.mysql.jdbc.Driver")
は不要とお話しましたが...
実は限定的な条件でのみでした。すみません。
Servletコンテナにデプロイされたwarや独自クラスローダを持つPlayなどは上記に当てはまらないため、Class.forNameが必要
play.runsupport.NamedURLClassLoader.scala
フルスタックフレームワークならば、
設定ファイルに書いておけば基本的に勝手にやってくれる
jmod形式
rt.jarにあたるものは
jmods/java.base.jmod
module hoge.piyo {
exports hoge.piyo;
requires hoge.fuga;
}
module-info.java
https://github.com/dmlloyd/openjdk
jdkのバージョンごとにブランチが切られていて便利
クローンはめっちゃ時間かかる
http://download.java.net/java/jdk9/docs/api/index.html?overview-summary.html
http://www.nminoru.jp/~nminoru/java/class_unloading.html