java ClassLoader机制和如何加载外部class文件(含代码)

Java类的生命周期

生命周期有:加载(Loading)–》验证(Verification)–》准备(Preparation)—》解析(Resolution)–》初始化(Initiation)—》使用(Using)—-》卸载(Unloading)。 其中标黄的验证—》准备—》解析被称为连接(Linking)。

就代码执行而言:

1.连接阶段:不执行程序员代码

2.加载阶段:可以重写ClassLoader来执行我们的代码

3.连接后阶段:执行该类的代码

ClassLoader:

ClassLoader是为了将class文件的byte数组,主要的方法是findClass用于查找类。

Java7有个迅速将File编程byte[]的方法:

byte[] cLassBytes = null;Path path;try {path = Paths.get(new URI("file:///D:/MyScript/TestClassLoader.class"));cLassBytes = Files.readAllBytes(path);

每个ClassLoader对象都有一个ClassLoader类型的字段,暂且成为parent。当调用本类的loadClass方法加载类时,会先调用parent的ClassLoader,如果他没找到,才会调用本类的findClass方法去查找类。(这样,应用的Launcher$AppClassLoader也可以通过BootStrapClassLoader来调用String类了)。

查找类的顺序,与对应的ClassLoader

系统查找类的顺序是:

1).Bootstrap classes: the runtime classes inrt.jar, internationalization classes ini18n.jar, and others.

2).Installed extensions: classes in JAR files in thelib/extdirectory of the JRE, and in the system-wide, platform-specific extension directory (such as/usr/jdk/packages/lib/exton the Solaris Operating System, but note that use of this directory applies only to Java 6 and later).

3).The class path: classes, including classes in JAR files, on paths specified by the system propertyjava.class.path. If a JAR file on the class path has a manifest with theClass-Pathattribute, JAR files specified by theClass-Pathattribute will be searched also. By default, thejava.class.pathproperty’s value is., the current directory. You can change the value by using the-classpathor-cpcommand-line options, or setting theCLASSPATHenvironment variable. The command-line options override the setting of theCLASSPATHenvironment variable.

中文就是:

1)rt.jar等(这个jar是什么呢?你用java -verbose 类名 运行下就看到了:Loaded java.io.File from C:\Program Files\Java\jre1.8.0_31\lib\rt.jar,也就是经常调用的String、Long等类,属于SDK中的)(用BootStrapClassLoader加载)

2)SDK中的拓展类,包名为javax的(java和javax都是Java的API(Application Programming Interface)包,java是核心包,javax的x是extension的意思);

(用Launcher$ExtClassLoader加载)

3)系统环境变量CLASSPATH的路径,当前目录(或者用命令行带 -classpath重新)

(用Launcher$AppClassLoader加载)

可是我的类文件在D:\MyScript\TestClassLoader.class不在上述三种。

2:解决方案

1.场景:我想加载一个d盘上的类,路径是:D:\MyScript\TestClassLoader.class,其不在上述三种情况。

通过重写一个ClassLoader进行加载,,不过有现成的URLClassLoader我们就不要重造轮子了。

自定义ClassLoader代码

public class MyClassLoader extends ClassLoader{@Overrideprotected Class<?> findClass(String className)throws ClassNotFoundException {byte[] cLassBytes = null;//Java 7有下列API<span style="white-space:pre"></span>Path path;try {path = Paths.get(new URI("file:///D:/MyScript/TestClassLoader.class"));cLassBytes = Files.readAllBytes(path);} catch (IOException | URISyntaxException e) {e.printStackTrace();}Class cLass = defineClass(cLassBytes, 0, cLassBytes.length);return cLass;}}使用的时候:

Class.forName("TestClassLoader", true, new MyClassLoader());

用URLClassLoader来简化

ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();// This URL for a directory will be searched *recursively*URL classes;try {classes = new URL( "file:///D:/MyScript/" );ClassLoader custom =new URLClassLoader( new URL[] { classes }, systemClassLoader );// this class should be loaded from your directoryClass< ? > clazz = custom.loadClass( "TestClassLoader" );Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {System.out.println(method.getName());}URLClassLoader用的URL只能接受目录和jar包:

结尾: /代表该目录下的来; 非/而是文件则默认为jar包。

贴一个jar包的代码:

public URL findResource(String name) {try {File file = new File(jarFile);String url = file.toURL().toString();return new URL("jar:"+url+"!/"+name);} catch (Exception e) {return null;}}<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);"></span>

另外我用反射来验证类是否加载成功了,clazz.newInstance()也可以生成相关代码。

年轻是我们唯一拥有权利去编织梦想的时光

java ClassLoader机制和如何加载外部class文件(含代码)

相关文章:

你感兴趣的文章:

标签云: