JVM类加载器
2015-11-03 20:05
211 查看
一:类加载器的层次结构 1、引导类加载器:用来加载java的核心库。 2、扩展类加载器:用来加载java的扩展库。实现类:sun.misc.Launcher$ExtClassLoader 3、应用类加载器:加载本应用所需要的类。实现类:sun.misc.Launcher$AppClassLoader 4、自定义类加载器 注意:1-4依次是后者的父类,但不是通过继承来实现的,而是通过组合来实现的 1不是用java实现的,而是用c语言,后面三者都是用java语言实现的,都实现了java.lang.ClassLoader类 二:类加载采用代理模式 一般的类加载使用双亲委托机制,这样做主要是为了安全。如程序员定义的java.lang.String永远都不能被加载。 并不是所有的都是使用双亲委托机制。 三:ClassLoader常用方法: getParent() loadClass(String name) findClass(String name) findLoadedClass(String name) defineClass(String name, byte[] b, int off, int len) resolveClass(Class<?> c) 四:自定义类加载器 继承java.lang.ClassLoader 重写findClass(String name)方法 1、文件类自定义加载器 2、网络类自定义加载器 两者操作差不多,只是.class文件源头一个来自于文件,一个来自于url指定的服务器。 加密的类加载器:就是用一定的算法,先对.class文件进行加密操作,然后用相应的解密算法解密并进行类加载。 注意:同一个类被同一个类加载器加载会得到相同的Class对象 同一个类被不同的类加载器加载会得到不同的Class对象 五:系统默认的类加载器是双亲委托机制,但并不是所有的类都要使用这种机制,如TOMCAT服务器就开始默认的类加载机制 而是使用自定义的类加载机制。 线程上线文类加载器,就可以用来获得当前线程的类加载器、修改当前线程的类加载器 Thread.currentThread().getContextClassLoader()获得当前线程的类加载器 Thread.currentThread().setContextClassLoader()设置当前线程的类加载器
1、文件类加载器:
package com.chen.File; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; /** * 自定义类加载器 * 1、文件类加载器 * @author CHJ * */ public class FileSystemClassLoader extends ClassLoader{ // 加载路径。如:F:/New 中的 com.chen.Base_Points.First.class private String rootDir; public FileSystemClassLoader(String rootDir) { this.rootDir = rootDir; } //重写方法 @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> c = findLoadedClass(name); if(c != null) { return c; }else{ // 这里为了简单不使用双亲委托模式 byte[] classData = getClassData(name); if(classData == null) { throw new ClassNotFoundException(); }else{ c = defineClass(name, classData, 0, classData.length);// defineClass为ClassLoader中的方法 } } return c; } /** * 将制定的.class文件写入字节数组中 * @param name * @return */ private byte[] getClassData(String name) { // 拼出.class文件的完整路径 String path = rootDir + "/" + name.replace('.', '/') + ".class"; InputStream is = null; ByteArrayOutputStream bos = null; try { is = new FileInputStream(path); bos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while((len = is.read(buffer)) != -1){ bos.write(buffer, 0, len); } bos.flush(); return bos.toByteArray(); } catch (Exception e) { e.printStackTrace(); return null; }finally{ try { if(is != null) { is.close(); } if(is != null) { bos.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
package com.chen.File; public class Test { public static void main(String[] args) throws Exception { FileSystemClassLoader loader = new FileSystemClassLoader("F:/New"); FileSystemClassLoader loader2 = new FileSystemClassLoader("F:/New"); Class<?> c1 = loader.loadClass("com.chen.Base_Points.First"); Class<?> c2 = loader.loadClass("com.chen.Base_Points.First"); Class<?> c3 = loader2.loadClass("com.chen.Base_Points.First"); Class<?> c4 = loader.loadClass("java.lang.String"); System.out.println(c1.hashCode()); System.out.println(c2.hashCode());// 同一个.class文件被同一个类加载器加载生成同一个Class对象 System.out.println(c3.hashCode());// 同一个.class文件被不同的类加载加载生成不同的Class对象 System.out.println(c1.getClassLoader());// 用自定义类加载器加载的 System.out.println(c4.getClassLoader());// 返回值为lang用引导构造器加载的 } }
2、加密型文件类加载器:
加密算法:
package com.chen.File_Encryption; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * 简单的加密工具(取反操作) * @author Administrator * */ public class EncryptionUtil { /** * 演示取反 * @param args */ public static void main(String[] args) { int a = 3;// 二进制为00000011 // 转换成二进制 System.out.println(Integer.toBinaryString(a));// 11 // 取反(做异或运算) System.out.println(Integer.toBinaryString(a^0xff));// 11111100 } /** * 加密方法:把一个文件中二进制全部取反 * @param src * @param dest */ public static void Encryption(String src, String dest) { InputStream is = null; OutputStream os = null; try { is = new FileInputStream(src); os = new FileOutputStream(dest); int temp = -1; while((temp = is.read()) != -1){ os.write(temp^0xff);// 取反操作 } os.flush(); } catch (Exception e) { e.printStackTrace(); }finally{ if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if(os != null){ try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
加密类加载器:
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; /** * 与加密类加载器相对应的解密类加载器 * @author CHJ * */ public class DeEncryptonClassLoader extends ClassLoader { // 加载路径。如:F:/New 中的 com.chen.Base_Points.First.class private String rootDir; public DeEncryptonClassLoader(String rootDir) { this.rootDir = rootDir; } //重写方法 @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> c = findLoadedClass(name); if(c != null) { return c; }else{ // 这里为了简单不使用双亲委托模式 byte[] classData = getClassData(name); if(classData == null) { throw new ClassNotFoundException(); }else{ c = defineClass(name, classData, 0, classData.length);// defineClass为ClassLoader中的方法 } } return c; } /** * 将制定的.class文件写入字节数组中 * @param name * @return */ private byte[] getClassData(String name) { // 拼出.class文件的完整路径 String path = rootDir + "/" + name.replace('.', '/') + ".class"; InputStream is = null; ByteArrayOutputStream bos = null; try { is = new FileInputStream(path); bos = new 4000 ByteArrayOutputStream(); /* byte[] buffer = new byte[1024]; int len = 0; while((len = is.read(buffer)) != -1){ bos.write(buffer, 0, len); } bos.flush(); return bos.toByteArray(); */ int temp = -1; while((temp = is.read()) != -1) { bos.write(temp^0xff);// 取反 } bos.flush(); return bos.toByteArray(); } catch (Exception e) { e.printStackTrace(); return null; }finally{ try{ if(is != null) { is.close(); } if(is != null) { bos.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
</pre><pre name="code" class="java"> public class Test { public static void main(String[] args) throws Exception { EncryptionUtil.Encryption("F:/New/HelloWorld.class", "F:/New/temp/HelloWorld.class"); System.out.println("加密成功"); // 用原来的类加载器加载加密的.class文件会报ClassFormatError //FileSystemClassLoader loader = new FileSystemClassLoader("F:/New/temp"); //Class<?> c = loader.loadClass("HelloWorld"); // 下面使用解密的类加载器进行加载 // 注意:这里的.class文件是我用记事本写的,不导入任何包。如果加载的.class文件中有import..,注意导入需要的包,还要注意路径 DeEncryptonClassLoader loader = new DeEncryptonClassLoader("F:/New/temp"); Class<?> c = loader.loadClass("HelloWorld"); System.out.println(c.getClassLoader()); } }
相关文章推荐
- hihocoder 1145
- nginx autoindex
- 文艺篇----《转机》[短文]
- 微信扫码下载APK解决方案
- adr adrl ldr mov总结整理
- SparkSQL与Hive的应用关系
- Codevs_P3185 队列练习1
- Oracle EBS工作流表Subject等字段取值为空解决方法
- iOS模糊效果使用第三方库FXBlurView
- 默认实参
- iOS9新特性之实现3DTouch就是So easy(更新Swift 版 )
- MySQL性能优化的最佳20+条经验
- 在AngularJS环境中使用PhantomJS截图
- linux下系统级入侵检测工具AIDE
- 获取一组radio中其中一个的值
- 手机移动web页面的排版与布局一点经验(尺寸单位兼容行。)
- 程序设计基石与实践系列之运算符与选择语句编程
- 第十五周第二天
- arm学习之汇编跳转指令总结
- 字符串转换时间的方法