能不做自己写个类,也叫java.lang.String
生活随笔
收集整理的這篇文章主要介紹了
能不做自己写个类,也叫java.lang.String
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://bbs.itheima.com/thread-51369-1-1.html
?
可以,但是即使你寫了這個類,也沒有用。這個問題涉及到加載器的委托機制,在類加載器的結構圖(在下面)中,
BootStrap是頂層父類,ExtClassLoader是BootStrap類的子類,ExtClassLoader又是AppClassLoader的父類
這里以java.lang.String為例,當我是使用到這個類時,Java虛擬機會將java.lang.String類的字節碼加載到內存中。
為什么只加載系統通過的java.lang.String類而不加載用戶自定義的java.lang.String類呢?
因加載某個類時,優先使用父類加載器加載需要使用的類。如果我們自定義了java.lang.String這個類,
加載該自定義的String類,該自定義String類使用的加載器是AppClassLoader,根據優先使用父類加載器原理,
AppClassLoader加載器的父類為ExtClassLoader,所以這時加載String使用的類加載器是ExtClassLoader,
但是類加載器ExtClassLoader在jre/lib/ext目錄下沒有找到String.class類。然后使用ExtClassLoader父類的加載器BootStrap,
父類加載器BootStrap在JRE/lib目錄的rt.jar找到了String.class,將其加載到內存中。這就是類加載器的委托機制。
所以,用戶自定義的java.lang.String不被加載,也就是不會被使用。
類加載器結構圖.png (72.83 KB, 下載次數: 0)
下載附件 ?保存到相冊
2013-5-23 16:40 上傳
類加載器結構圖
?
http://rainlife.iteye.com/blog/70072
JVM在加載類的時候,都是通過ClassLoader的loadClass()方法來加載class的,loadClass(String name)方法:public Class<?> loadClass(String name) throws ClassNotFoundException {return loadClass(name, false);}
loadClass(String name)方法再調用loadClass(String name, boolean resolve)方法:
???? - name - 類的二進制名稱
???? - resolve - 如果該參數為 true,則分析這個類
protected synchronized Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{// First, check if the class has already been loaded//JVM 規范規定ClassLoader可以在緩存保留它所加載的Class,如果一個Class已經被加載過,則直接從緩存中獲取Class c = findLoadedClass(name);if (c == null) {try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClass0(name);}} catch (ClassNotFoundException e) {// If still not found, then invoke findClass in order// to find the class.c = findClass(name);}}if (resolve) {resolveClass(c);}return c; }
如果ClassLoader并沒有加載這個class,則調用findBootstrapClass0:
private Class findBootstrapClass0(String name)throws ClassNotFoundException{check();if (!checkName(name))throw new ClassNotFoundException(name);return findBootstrapClass(name);}
該方法會調用check()方法來判斷這個類是否已經初始化,并且通過checkName(name)來判斷由name指定的這個類是否存在
最后調用findBootstrapClass(name):
private native Class findBootstrapClass(String name)throws ClassNotFoundException;
而這個findBootstrapClass方法是一個native方法,這是我們的root loader,這個載入方法并非是由JAVA所寫,而是C++寫的,它會最終調用JVM中的原生findBootstrapClass方法來完成類的加載。
如果上面兩個都找不到,則使用findClass(name)來查找指定類名的Class:
protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name); }
JDK5.0中的說明:
使用指定的二進制名稱查找類。此方法應該被類加載器的實現重寫,該實現按照委托模型來加載類。在通過父類加載器檢查所請求的類后,此方法將被 loadClass 方法調用。默認實現拋出一個 ClassNotFoundException。
所以,我們在自定義類中,只需要重寫findClass()即可。
MyClassLoader類:
extends ClassLoader {private String fileName;public MyClassLoader(String fileName) {this.fileName = fileName;}protected Class<?> findClass(String className) throws ClassNotFoundException {Class clazz = this.findLoadedClass(className);if (null == clazz) {try {String classFile = getClassFile(className);FileInputStream fis = new FileInputStream(classFile);FileChannel fileC = fis.getChannel();ByteArrayOutputStream baos = newByteArrayOutputStream();WritableByteChannel outC = Channels.newChannel(baos);ByteBuffer buffer = ByteBuffer.allocateDirect(1024);while (true) {int i = fileC.read(buffer);if (i == 0 || i == -1) {break;}buffer.flip();outC.write(buffer);buffer.clear();}fis.close();byte[] bytes = baos.toByteArray();clazz = defineClass(className, bytes, 0, bytes.length);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}return clazz;}private byte[] loadClassBytes(String className) throwsClassNotFoundException {try {String classFile = getClassFile(className);FileInputStream fis = new FileInputStream(classFile);FileChannel fileC = fis.getChannel();ByteArrayOutputStream baos = newByteArrayOutputStream();WritableByteChannel outC = Channels.newChannel(baos);ByteBuffer buffer = ByteBuffer.allocateDirect(1024);while (true) {int i = fileC.read(buffer);if (i == 0 || i == -1) {break;}buffer.flip();outC.write(buffer);buffer.clear();}fis.close();return baos.toByteArray();} catch (IOException fnfe) {throw new ClassNotFoundException(className);}}private String getClassFile(String name) {StringBuffer sb = new StringBuffer(fileName);name = name.replace('.', File.separatorChar) + ".class";sb.append(File.separator + name);return sb.toString();} }
該類中通過調用defineClass(String name, byte[] b, int off, int len)方法來定義一個類:
protected final Class<?> defineClass(String name, byte[] b, int off, int len)throws ClassFormatError{return defineClass(name, b, off, len, null);}
注:MyClassLoader加載類時有一個局限,必需指定.class文件,而不能指定.jar文件。該類中的大部分代碼是從網上搜索到的,是出自一牛人之筆,只是不知道原帖在哪,希望不會被隱藏。
MainClassLoader類:
public class MainClassLoader {public static void main(String[] args) {try {MyClassLoader tc = new MyClassLoader("F:\\OpenLib\\");Class c = tc.findClass("Test");c.newInstance();} catch (ClassNotFoundException e) {e.printStackTrace(); } catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace(); }} }
最后是一個簡單的Test測試類:
public class Test {public Test() {System.out.println("Test");}public static void main(String[] args) {System.out.println("Hello World");} }
?
總結
以上是生活随笔為你收集整理的能不做自己写个类,也叫java.lang.String的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stop() 和 suspend() 方
- 下一篇: 有关Vector里面元素重复解决办法