Je regardais récemment la machine virtuelle Java, et la section du chargeur de classe a donné cet exemple :
/**
*类加载器与instanceof关键字演示
**
@author zzm
*/
public class ClassLoaderTest{
public static void main(String[]args) throws Exception{
ClassLoader myLoader=new ClassLoader(){
@Override
public Class<?>loadClass(String name)throws ClassNotFoundException{
try{
String fileName=name.substring(name.lastIndexOf(".")+1)+".class";
InputStream is=getClass().getResourceAsStream(fileName);
if(is==null){
return super.loadClass(name);
}
byte[]b=new byte[is.available()];
is.read(b);
return defineClass(name,b,0,b.length);
}
catch(IOException e){
throw new ClassNotFoundException(name);
}
}
}
;
Object obj=myLoader.loadClass("org.fenixsoft.classloading.ClassLoaderTest").newInstance();
System.out.println(obj.getClass());
System.out.println(obj instanceof org.fenixsoft.classloading.ClassLoaderTest);//false
}
}
En bref, utilisez un chargeur de classe personnalisé pour charger une classe. La classe renvoyée est différente de la classe chargée par le SystemClassLoader fourni avec le jvm.
Ensuite, si vous utilisez une classe qui hérite de ClasserLoader, il va de soi qu'elle aura le même effet
package jvm;
public class MyClassLoader extends ClassLoader{
@Override
public Class<?> loadClass(String fullClassName) throws ClassNotFoundException{
try {
String fileName = fullClassName.substring(fullClassName.lastIndexOf(".")+1,fullClassName.length())+".class";
InputStream is = getResourceAsStream(fileName);
if(is==null){
return super.loadClass(fullClassName);
}
byte[] bytes = new byte[is.available()];
is.read(bytes);
return defineClass(fullClassName,bytes,0,bytes.length);
}catch (Exception e){
throw new ClassNotFoundException();
}
}
public static void main(String[] args) throws Exception{
ClassLoader myClassLoader = new MyClassLoader();
/**
ClassLoader myClassLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String fullClassName) throws ClassNotFoundException {
try {
String fileName = fullClassName.substring(fullClassName.lastIndexOf(".")+1,fullClassName.length())+".class";
InputStream is = getClass().getResourceAsStream(fileName);
if(is==null){
return super.loadClass(fullClassName);
}
byte[] bytes = new byte[is.available()];
is.read(bytes);
return defineClass(fullClassName,bytes,0,bytes.length);
}catch (Exception e){
throw new ClassNotFoundException();
}
}
};
/**/
ClassLoader systemClassLoader = java.lang.ClassLoader.getSystemClassLoader();
Class myClass = myClassLoader.loadClass("jvm.MyClassLoader");
Class systemClass = systemClassLoader.loadClass("jvm.MyClassLoader");
Object myObj = myClass.newInstance();
Object systemObj = systemClass.newInstance();
System.out.println(myClass.equals(systemClass));//true
System.out.println(myObj.getClass().equals(systemObj.getClass()));//true
}
}
Le code dans le commentaire est l'héritage de la classe interne anonyme. Notez que myClass et systemClass sont complètement égaux, mais myClass est généré à l'aide de la classe MyClassLoader qui hérite de ClassLoader. Pourquoi ? . .
Le deuxième code va à
Chargement
class
文件用getClass().getResourceAsStream