能不做自己写个类,也叫java.lang.String
生活随笔
收集整理的這篇文章主要介紹了
能不做自己写个类,也叫java.lang.String
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://bbs.itheima.com/thread-51369-1-1.html
?
可以,但是即使你寫(xiě)了這個(gè)類(lèi),也沒(méi)有用。這個(gè)問(wèn)題涉及到加載器的委托機(jī)制,在類(lèi)加載器的結(jié)構(gòu)圖(在下面)中,
BootStrap是頂層父類(lèi),ExtClassLoader是BootStrap類(lèi)的子類(lèi),ExtClassLoader又是AppClassLoader的父類(lèi)
這里以java.lang.String為例,當(dāng)我是使用到這個(gè)類(lèi)時(shí),Java虛擬機(jī)會(huì)將java.lang.String類(lèi)的字節(jié)碼加載到內(nèi)存中。
為什么只加載系統(tǒng)通過(guò)的java.lang.String類(lèi)而不加載用戶(hù)自定義的java.lang.String類(lèi)呢?
因加載某個(gè)類(lèi)時(shí),優(yōu)先使用父類(lèi)加載器加載需要使用的類(lèi)。如果我們自定義了java.lang.String這個(gè)類(lèi),
加載該自定義的String類(lèi),該自定義String類(lèi)使用的加載器是AppClassLoader,根據(jù)優(yōu)先使用父類(lèi)加載器原理,
AppClassLoader加載器的父類(lèi)為ExtClassLoader,所以這時(shí)加載String使用的類(lèi)加載器是ExtClassLoader,
但是類(lèi)加載器ExtClassLoader在jre/lib/ext目錄下沒(méi)有找到String.class類(lèi)。然后使用ExtClassLoader父類(lèi)的加載器BootStrap,
父類(lèi)加載器BootStrap在JRE/lib目錄的rt.jar找到了String.class,將其加載到內(nèi)存中。這就是類(lèi)加載器的委托機(jī)制。
所以,用戶(hù)自定義的java.lang.String不被加載,也就是不會(huì)被使用。
類(lèi)加載器結(jié)構(gòu)圖.png (72.83 KB, 下載次數(shù): 0)
下載附件 ?保存到相冊(cè)
2013-5-23 16:40 上傳
類(lèi)加載器結(jié)構(gòu)圖
?
http://rainlife.iteye.com/blog/70072
JVM在加載類(lèi)的時(shí)候,都是通過(guò)ClassLoader的loadClass()方法來(lái)加載class的,loadClass(String name)方法:public Class<?> loadClass(String name) throws ClassNotFoundException {return loadClass(name, false);}
loadClass(String name)方法再調(diào)用loadClass(String name, boolean resolve)方法:
???? - name - 類(lèi)的二進(jìn)制名稱(chēng)
???? - resolve - 如果該參數(shù)為 true,則分析這個(gè)類(lèi)
protected synchronized Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{// First, check if the class has already been loaded//JVM 規(guī)范規(guī)定ClassLoader可以在緩存保留它所加載的Class,如果一個(gè)Class已經(jīng)被加載過(guò),則直接從緩存中獲取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并沒(méi)有加載這個(gè)class,則調(diào)用findBootstrapClass0:
private Class findBootstrapClass0(String name)throws ClassNotFoundException{check();if (!checkName(name))throw new ClassNotFoundException(name);return findBootstrapClass(name);}
該方法會(huì)調(diào)用check()方法來(lái)判斷這個(gè)類(lèi)是否已經(jīng)初始化,并且通過(guò)checkName(name)來(lái)判斷由name指定的這個(gè)類(lèi)是否存在
最后調(diào)用findBootstrapClass(name):
private native Class findBootstrapClass(String name)throws ClassNotFoundException;
而這個(gè)findBootstrapClass方法是一個(gè)native方法,這是我們的root loader,這個(gè)載入方法并非是由JAVA所寫(xiě),而是C++寫(xiě)的,它會(huì)最終調(diào)用JVM中的原生findBootstrapClass方法來(lái)完成類(lèi)的加載。
如果上面兩個(gè)都找不到,則使用findClass(name)來(lái)查找指定類(lèi)名的Class:
protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name); }
JDK5.0中的說(shuō)明:
使用指定的二進(jìn)制名稱(chēng)查找類(lèi)。此方法應(yīng)該被類(lèi)加載器的實(shí)現(xiàn)重寫(xiě),該實(shí)現(xiàn)按照委托模型來(lái)加載類(lèi)。在通過(guò)父類(lèi)加載器檢查所請(qǐng)求的類(lèi)后,此方法將被 loadClass 方法調(diào)用。默認(rèn)實(shí)現(xiàn)拋出一個(gè) ClassNotFoundException。
所以,我們?cè)谧远x類(lèi)中,只需要重寫(xiě)findClass()即可。
MyClassLoader類(lèi):
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();} }
該類(lèi)中通過(guò)調(diào)用defineClass(String name, byte[] b, int off, int len)方法來(lái)定義一個(gè)類(lèi):
protected final Class<?> defineClass(String name, byte[] b, int off, int len)throws ClassFormatError{return defineClass(name, b, off, len, null);}
注:MyClassLoader加載類(lèi)時(shí)有一個(gè)局限,必需指定.class文件,而不能指定.jar文件。該類(lèi)中的大部分代碼是從網(wǎng)上搜索到的,是出自一牛人之筆,只是不知道原帖在哪,希望不會(huì)被隱藏。
MainClassLoader類(lèi):
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(); }} }
最后是一個(gè)簡(jiǎn)單的Test測(cè)試類(lèi):
public class Test {public Test() {System.out.println("Test");}public static void main(String[] args) {System.out.println("Hello World");} }
?
總結(jié)
以上是生活随笔為你收集整理的能不做自己写个类,也叫java.lang.String的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: stop() 和 suspend() 方
- 下一篇: 有关Vector里面元素重复解决办法