Java

当前位置:首页 > Java

Java自定义类的加载器 - Java

Java程序在运行的时候,JVM通过类加载机制(ClassLoader)把class文件加载到内存中,只有class文件被载入内存,才能被其他class引用,使程序正确运行起来.Java中的ClassLoader有三种...

Java程序在运行的时候,JVM通过类加载机制(ClassLoader)把class文件加载到内存中,只有class文件被载入内存,才能被其他class引用,使程序正确运行起来.


Java中的ClassLoader有三种:Bootstrap ClassLoader 、Extension ClassLoader、App ClassLoader。

1. Bootstrap ClassLoader

由C++写的,由JVM启动.

启动类加载器,负责加载java基础类,对应的文件是%JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等

2.Extension ClassLoader

Java类,继承自URLClassLoader 扩展类加载器,

对应的文件是 %JRE_HOME/lib/ext 目录下的jar和class等

3.App ClassLoader

Java类,继承自URLClassLoader 系统类加载器,

对应的文件是应用程序classpath目录下的所有jar和class等


Java的加载机制是双亲委派机制来加载类

为什么要使用这种方式?这个是为了保证 如果加载的类是一个系统类,那么会优先由Bootstrap ClassLoader 、Extension ClassLoader先去加载,而不是使用我们自定义的ClassLoader去加载,保证系统的安全!


系统的ClassLoader只会加载指定目录下的class文件,如果你想加载自己的class文件,那么就可以自定义一个ClassLoader。

新建一个类继承自java.lang.ClassLoader,重写它的findClass方法,然后将class字节码数组转换为Class类的实例,调用loadClass方法即可。


新建一个样品Java文件,并生成class,然后拷贝到指定目录

package com.javacui.test;public class ClassLoaderTest {    public static void main(String[] args) {        System.out.println("I am ClassLoaderTest");        for (String str : args){            System.out.println("参数:" + str);        }    }}


自定义一个类加载器,加载该class文件并调用main方法

import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.lang.reflect.Method;public class MyClassLoader extends ClassLoader {    public static void main(String[] args) throws Exception {        //这个类class的路径        String classPath = "D://temp/ClassLoaderTest.class";        //类的全称,有包名的加包名        String packageNamePath = "com.javacui.test.ClassLoaderTest";        MyClassLoader myClassLoader = new MyClassLoader(classPath);        //加载ClassLoaderTest类的class文件        Class<?> myclass = myClassLoader.loadClass(packageNamePath);        System.out.println("类加载器是:" + myclass.getClassLoader());        //利用反射获取main方法        Method method = myclass.getDeclaredMethod("main", String[].class);        Object object = myclass.newInstance();        String[] arg = {"java小强", "博客"};        method.invoke(object, (Object) arg);    }    //指定路径    private String path;    public MyClassLoader(String classPath) {        path = classPath;    }    /**     * 重写findClass方法     *     * @param name 是我们这个类的全路径     * @throws ClassNotFoundException     */    @Override    protected Class<?> findClass(String name) throws ClassNotFoundException {        Class myclass = null;        // 获取该class文件字节码数组        byte[] classData = getData();        if (classData != null) {            // 将class的字节码数组转换成Class类的实例            myclass = defineClass(name, classData, 0, classData.length);        }        return myclass;    }    /**     * 将class文件转化为字节码数组     */    private byte[] getData() {        File file = new File(path);        if (file.exists()) {            FileInputStream in = null;            ByteArrayOutputStream out = null;            try {                in = new FileInputStream(file);                out = new ByteArrayOutputStream();                byte[] buffer = new byte[1024];                int size = 0;                while ((size = in.read(buffer)) != -1) {                    out.write(buffer, 0, size);                }            } catch (IOException e) {                e.printStackTrace();            } finally {                try {                    in.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            return out.toByteArray();        } else {            return null;        }    }}


输出

类加载器是:sun.misc.Launcher$AppClassLoader@14dad5dcI am ClassLoaderTest参数:java小强参数:博客


如果想要保护你的class文件,那可以借助自定义类加载器,因为java的class文件是可以被轻易反编译的。

例如上面,我们生成class文件后,可以通过对称加密等方式进行加密,那么拿到的class字节都是加密后,是无法使用的,在上面的getData()方法中我们读取到了文件字节流,可以把该字节流再进行解密。


DES加密使用入门 http://www.javacui.com/java/17.html 

JAVA加密算法实现用例 密钥一致协议 http://www.javacui.com/Theory/273.html 

JAVA加密算法实现用例 数字签名 http://www.javacui.com/java/312.html 


相关内容

文章评论

表情

共 0 条评论,查看全部
  • 这篇文章还没有收到评论,赶紧来抢沙发吧~

评论排行榜

热门标签