自定义类加载器在复杂类加载情况下的运行分析
生活随笔
收集整理的這篇文章主要介紹了
自定义类加载器在复杂类加载情况下的运行分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在之前咱們都在研究自定義類加載器的一些東東,不過接一來的學習還會依托于之前咱們寫的MyTest16這個自定義類加載器,這里先再回顧一下:
public class MyTest16 extends ClassLoader {private String classLoaderName;/* 從什么地方去加載,這是個絕對路徑 */private String path;private final String fileExtension = ".class";//要加載的字節碼文件的擴展名public MyTest16(String classLoaderName) {super();//將系統類加載器當作該類加載器的父加載器this.classLoaderName = classLoaderName;}public MyTest16(ClassLoader parent, String classLoaderName) {super(parent);//顯示指定該類加載器的父加載器this.classLoaderName = classLoaderName;}public void setPath(String path) {this.path = path;}@Overridepublic String toString() {return "[" + classLoaderName + "]";}@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {System.out.println("findClass invoked: " + className);System.out.println("class loader name: " + this.classLoaderName);byte[] data = this.loadClassData(className);return this.defineClass(className, data, 0, data.length);}private byte[] loadClassData(String className) {InputStream is = null;byte[] data = null;ByteArrayOutputStream baos = null;className = className.replace(".", "/");//由于路徑名需要以/分隔,而不是像包名以.分隔的try {is = new FileInputStream(new File(this.path + className + this.fileExtension));baos = new ByteArrayOutputStream();int ch = 0;while (-1 != (ch = is.read())) {baos.write(ch);}data = baos.toByteArray();} catch (Exception ex) {ex.printStackTrace();} finally {try {is.close();baos.close();} catch (Exception ex) {ex.printStackTrace();}}return data;}public static void main(String[] args) throws Exception {MyTest16 loader1 = new MyTest16("loader1");Class<?> clazz = loader1.loadClass("com.jvm.classloader.MyTest1");System.out.println("class:" + clazz.hashCode());System.out.println("classloader:" + clazz.getClassLoader());Object object = clazz.newInstance();System.out.println(object);System.out.println();} }而對于之前咱們加載的類都是一個比較簡單的類,如MyTest1:
但是在日常開發中可能常見的用法是方法里面會使用其它的類,那如果是這種情況類的加載的流程是一個什么情況呢,下面來探討一下:
首先新建一個MyCat類:
?
然后再新建一個MySample類:
目前這兩個類木有任何關系,接下來將其關聯起來:
好,接下來應用一下:
其結果:
很明顯由于MySample的字節碼文件存在于工程當中,所以肯定是由系統類加載了,接下來將這句代碼注釋掉:
編譯運行:
也就是注釋之后則不會實例化MySample對象,既MySample構造方法不會被調用,因此也不會實例化MyCat對象,既沒有對MyCat進行主動使用,這里就不會加載MyCat Class。其實類加載器會不會加載MyCat這是不一定的,這是因為如下原因:
- 類加載器并不需要等到某個類被“首次主動使用”時再加載它。
- JVM規范允許類加載器在預料某個類將要被使用時就預先加載它,如果在預先加載的過程中遇到了.class文件缺失或存在錯誤,類加載器必須在程序首次主動使用該類時才報告錯誤(LinkageError錯誤)。
- 如果這個類一直沒有被程序主動使用,那么類加載器就不會報告錯誤。
所以MyCat類雖說沒有被初始化,那它到底有木有被加載可以通過給JVM增加"-XX:+TraceClassLoading"來看一下:
但是這不代表JVM一定不會加載MyCat這個類,需要注意。
轉載于:https://www.cnblogs.com/webor2006/p/9129149.html
總結
以上是生活随笔為你收集整理的自定义类加载器在复杂类加载情况下的运行分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hashtable元素的删除
- 下一篇: vue通信