标签:[] invoke obj 符号 tput puts null classpath xtend
假如,你开发的java程序都需要从E:\classloader1目录下的类文件中加载class,而不是系统指定的系统目录或者classpath目录下加载,则如何解决? 需要自定义classloader。ClassLoader:加载各种class文件到JVM中。ClassLoader是抽象类。
类的加载过程分为加载阶段、连接阶段、初始化。
JVM目前对类的初始化时一次lazy。所以何时初始化就会根据不同情况而不同,如果主动使用,则会进行类的初始化。
类的6种主动使用情况:
类的被动使用:除了主动的以外,都是被动的。
类的加载过程中阶段,常量是在javac编译阶段就替换了值,所以不会再类的连接阶段进行默认初始化(给相应类变量一个相关类型在没有被设置时候的默认值)。
类的初始化阶段中,赋值动作和静态语句块的执行代码,这个是按照顺序执行。虚拟机会保证这些动作会优先执行,因此父类的静态变量总是能够得到优先赋值。
JVM默认的加载类去寻找特定的几个目录下的类进行加载。比如当前路径,classpath等。若想自定义路径,或者在加载过程中,有些个性化的需求,则需要自定义加载类进行加载。
自定义加载类,还有一个好处,可以根据需求,进行单独卸载和重新加载,这样就可以进行无需停机的热部署。
下面时自定义加载类的使用方法:
}
‘‘‘
其中findClass是必须重写的,功能就是读入class文件位字节流,然后调用ClassLoader的自带方法defineClass方法对类在方法区进行定义,这样,才能使用这个自定义类。
‘‘‘
package classLoaderStudy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class MyClassLoader extends ClassLoader{
private final static Path DEFAULT_CLASS_DIR = Paths.get("E:", "classloader1");
private final Path classDir;
public MyClassLoader()
{
super();
this.classDir = DEFAULT_CLASS_DIR;
}
public MyClassLoader(String classDir)
{
super();
this.classDir = Paths.get(classDir);
}
public MyClassLoader(String classDir,ClassLoader parent)
{
super(parent);
this.classDir = Paths.get(classDir);
}
private byte[] readClassBytes(String name)
throws ClassNotFoundException
{
String classPath = name.replace(".", "/");
Path classFullPath = classDir.resolve(Paths.get(classPath+".class"));
if(!classFullPath.toFile().exists())
{
throw new ClassNotFoundException("The Class "+name+" not found");
}
try(ByteArrayOutputStream baos = new ByteArrayOutputStream())
{
Files.copy(classFullPath, baos);
return baos.toByteArray();
}
catch(IOException e)
{
throw new ClassNotFoundException("Load the class "+ name +" occur error.",e);
}
}
@Override
/*
* (non-Javadoc)
* @see java.lang.ClassLoader#findClass(java.lang.String)
* 必须要重写这个类
*/
protected Class<?> findClass(String name) throws ClassNotFoundException
{
byte[] classBytes = this.readClassBytes(name);
if(null == classBytes || classBytes.length == 0)
{
throw new ClassNotFoundException("can not load the class ");
}
return this.defineClass(name, classBytes, 0,classBytes.length);
}
@Override
public String toString()
{
return "My ClassLoader";
}
public static void main(String[] args) {
MyClassLoader classLoader = new MyClassLoader();
Class<?> aClass =null;
try {
aClass = classLoader.loadClass("classLoaderStudy.ClassLoaderHello");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(aClass.getClassLoader());
try {
Object helloWorld = aClass.newInstance();
System.out.println(helloWorld);
Method welcomeMethod = aClass.getMethod("welcome");
String result = (String) welcomeMethod.invoke(helloWorld);
System.out.println(result);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}catch (Exception e)
{
e.printStackTrace();
}
}
}
‘‘‘
将classLoaderStudy\\ClassLoaderHello.class
文件拷贝到 E:\\classloader1
目录下,
如E:\\classloader1\\classLoaderStudy\\ClassLoaderHello.class
并将工程中的 ClassLoaderHello.java
文件和ClassLoaderHello.class
文件删除,从而确保不会加载工程中的这个类,以便测试自定义加载类。
在Eclipse中运行MyClassLoader
类,结果如下
‘‘‘
My ClassLoader
hello worldbr/>classLoaderStudy.ClassLoaderHello@7d4991ad
Hello world
‘‘‘
标签:[] invoke obj 符号 tput puts null classpath xtend
原文地址:http://blog.51cto.com/ggwhsd/2347326