1.自己创建的java.lang.String类无法被加载
加载String类的时候,是由类加载器一层层往上传递到BootstrapClassLoader加载的,所以下层的类是没有机会加载的。
自己创建的java.lang.String类是无法被加载的,具体原因可参考:
链接描述
如果自己创建java.lang.String类,如果没有自定义ClassLoader走的还是双亲委派的道路,默认情况下JVM不会加载我们自定义的String类。
但是自己定义的ClassLoader,进行loadClass时会自动调用父类的defineClass,defineClass中有一个preDefineClass方法,它里面会自动判断包名,
如果以java开头,就会报SecurityException异常
2.改包名,使用自定义ClassLoader加载
- MyClassLoader.java
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
public class MyClassLoader extends ClassLoader{
// 设置自己的类路径名
private String classPath;
// 创建1个Map存储自己创建的类的全限定名
private Map<String, String> createMap;
public MyClassLoader(){
createMap = new HashMap<>();
}
// 加载类
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// 加载的时候只有1个线程
synchronized(getClassLoadingLock(name)){
// 判断当前类是否已经被加载
Class<?> c = findLoadedClass(name);
// 如果没有被加载
if(c == null){
// 如果是自己创建的类
if(createMap.containsKey(name)){
c = findClass(name);
}else{
// 走双亲委派机制,进行加载
c = this.getParent().loadClass(name);
}
}
if(resolve){
resolveClass(c);
}
return c;
}
}
// 将自己创建的类添加到HashMap中
public boolean addCreateClass(String name){
if(name != null && !createMap.containsKey(name)){
createMap.put(name, name);
return true;
}
return false;
}
// 手动加载已创建的类
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException{
try{
byte[] data = loadByte(name);
// defineClass将一个字节数组转换为Class对象
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
private byte[] loadByte(String name) throws Exception{
// name中肯定会有.,为了避免转义,替换成路径/
System.out.println(name);
name = name.replaceAll("\\.", Matcher.quoteReplacement(File.separator));
// 加载这个文件,然后进行读取
FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
// 文件的长度
int len = fis.available();
byte[] byteArr = new byte[len];
// 将文件转换为字节流
fis.read(byteArr);
fis.close();
return byteArr;
}
// 设置类的路径
public void setClassPath(String classPath) {
this.classPath = classPath;
}
}
- com.wu.String类
package com.wu;
public class String {
private int id;
private java.lang.String name;
public java.lang.String getName(){
return "this is my created String";
}
}
该类需要编译成.class文件
我是在是cmd中使用 javac String.java编译的
来看测试类代码
结果展示:
使用自己创建的: class com.wu.String
官方自带的: class java.lang.String