java高新技术-类加载器
1.类加载器及委托机制的深入分析
> 类加载器的作用:一个java文件中的出现的类,首先要把这个类的字节码加载到内存中,这个类的信息放在硬盘的classPath下的class文件中,
把class文件中的内容加载到内存中去,在进行一些处理,处理完的结果就是字节码,这一系列工作是类加载器在做。
> Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap,ExtClassLoader, AppClassLoader
> 类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,
这正是BootStrap
BootStrap 很特殊,不是一个java类,是嵌套在jvm内核里的,jvm内核一启动BootStrap就已经在那里边了,BootStrap是由C++语言写的一段二进制代码,可以去加载别的类,包括别的类加载器
System类是由BootStrap类加载器加载
用eclipse 的打包工具将ClassLoaderTest 输出成jre/lib/ext 目录下的itcast.jar包,再在eclipse中运行这个类,运行结果显示为ExtClassLoader。此时的环境状态时classpath目录有ClassLoaderTest.class, ext/itcast.jar 包中也有ClassLoaderTest.class。
当ExtClassLoader中能找到时,使用的是ExtClassLoader,当ExtClassLoader中找不到时,会去AppClassLoader中找,这里的原理是类加载器的委托机制。
- public static void main(String[] args) {
- System.out.println(ClassLoaderTest.class.getClassLoader().getClass()
- .getName()); //sun.misc.Launcher$AppClassLoader
- /**
- * System 的类加载器为null 不代表没有类加载器,代表是由一个特殊的类加载器加载 BootStrap类加载器
- * 因为是嵌套在jvm里的,用java获取肯定获取不到,所有为null
- */
- System.out.println(System.class.getClassLoader()); //null
- /**
- * 以下程序打印
- * sun.misc.Launcher$AppClassLoader
- sun.misc.Launcher$ExtClassLoader
- null
- */
- ClassLoader loader = ClassLoaderTest.class.getClassLoader();
- while(loader != null){
- System.out.println(loader.getClass().getName());
- loader = loader.getParent();
- }
- System.out.println(loader);
- }
sun.misc.Launcher$ExtClassLoader
2.类加载器的委托机制
2.1.可以定义类加载器,自定义类加载器需要继承ClassLoader,自定义的类加载器可以指定一个特定的目录
2.2 当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
> 首先当前线程的类加载器去加载线程中的第一个类。getContextClassLoader()
setContextClassLoader(ClassLoader cl)
> 如果类A 中引用了类B ,Java虚拟机将使用加载类A的类加载器来加载类B。
> 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
2.3 每个类加载器加载类时,又先委托给其上级加载器。
> 当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,
不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多少个儿子呢,找哪一个呢?
> 对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jar/lib/ext 目录下
的itcast.jar包中后,运行结果为ExtClassLoader的原因
2.4 模板方法设计模式
父类 -->loadClass/findClass
|----子类1(自己干)
|----子类2(自己干)
每个子类都有自己的方法逻辑,每个子类加载时都会去找其父节点,这个流程每个子类都会有,所以这个代码放在父类中
我们要覆盖的是findClass,如果覆盖loadClass就会破坏这个流程
得到class文件的转换成字节码 --> definedClass()
protected Class<?> |
defineClass(String name, byte[] b, int off, int len) |
Api中的一段代码:
- The network class loader subclass must define the methods findClass and loadClassData to load a class from the network. Once it has downloaded the bytes that make up the class, it should use the method defineClass to create a class instance. A sample implementation is:
- class NetworkClassLoader extends ClassLoader {
- String host;
- int port;
- public Class findClass(String name) {
- byte[] b = loadClassData(name);
- return defineClass(name, b, 0, b.length);
- }
- private byte[] loadClassData(String name) {
- // load the class data from the connection
- . . .
- }
- }
编写对class文件进行加密的工具类
- public class MyclassLoader {
- public static void main(String[] args) throws Exception {
- String srcPath = args[0];
- String destDir = args[1];
- FileInputStream fis = new FileInputStream(srcPath);
- String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
- String destPath = destDir + "\\" + destFileName;
- FileOutputStream fos = new FileOutputStream(destPath);
- cypher(fis, fos);
- fos.close();
- fis.close();
- }
- /**
- * 加密
- * @param is
- * @param ot
- * @throws IOException
- */
- private static void cypher(InputStream is,OutputStream ot) throws IOException{
- int b = -1;
- while((b = is.read()) != -1){
- ot.write(b ^ 0xff); //异或 0变1 1变0
- }
- }
- }
在工程目录下新建一个文件夹 itcastlib
点击鼠标右键-> Run Configuration 填入运行参数
运行后,在文件夹itcastlib中新增一个class文件
有包名的类不能调用无包名的类
使用正常的class文件能够正常打印
System.out.println(new ClassLoaderAttachment().toString());
使用加密后的class文件替换正常的没有加密的class文件,并打印toString()
则会抛出异常
必须用自定义的类加载器,对加密的class可以进行解密的操作
- private String classDir;
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- String classFileName = classDir + "\\" + name + ".class";
- try {
- FileInputStream fis = new FileInputStream(classFileName);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- cypher(fis, bos);
- fis.close();
- byte[] bytes = bos.toByteArray();
- return defineClass(bytes, 0, bytes.length);
- } catch (Exception e) {
- }
- return null;
- }
- public MyclassLoader(String classDir){
- this.classDir = classDir;
- }
Class clazz = new MyclassLoader("itcastlib").loadClass("ClassLoaderAttachment");
Date d1 = (Date)clazz.newInstance(); //ClassLoaderAttachment这个类不能显示出现,因为这个类还是乱的
System.out.println(d1); //hello,itcast 解密成功
java高新技术-类加载器的更多相关文章
- java自定义类加载器
前言 java反射,最常用的Class.forName()方法.做毕设的时候,接收到代码字符串,通过 JavaCompiler将代码字符串生成A.class文件(存放在classpath下,也就是ec ...
- Java虚拟机类加载器及双亲委派机制
所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...
- 深入探讨java的类加载器
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Ja ...
- java 中类加载器
jar 运行过程和类加载机制有关,而类加载机制又和我们自定义的类加载器有关,现在我们先来了解一下双亲委派模式. java 中类加载器分为三个: BootstrapClassLoader 负责加载 ${ ...
- 深入理解Java虚拟机 - 类加载器
引子: 类加载器(classloader)是独立于虚拟机之外,可以独立实现的代码模块. OSGi使用了类加载器的这一特点实现其热插拔的特性 Java同C++等语言不通, ...
- 分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码
先回顾一下classpath classpath的作用: classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类. 指 ...
- java面向对象--类加载器及Class对象
类加载器 jvm 和 类的关系 当调用 java命令运行一个java程序时,会启动一个java虚拟机进程.同一个jvm的所有线程.所有变量都处于同一个进程里,都使用该jvm进程的内存区. jvm进程终 ...
- Java的类加载器
一.类加载器的概念 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 ...
- Java的类加载器种类(双亲委派)
Java类加载器采用双亲委派模型: 1.启动类加载器:这个类加载器负责放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别 ...
随机推荐
- nginx限制上传大小和超时时间设置说明/php限制上传大小
现象说明:在服务器上部署了一套后台环境,使用的是nginx反向代理tomcat架构,在后台里上传一个70M的视频文件,上传到一半就失效了! 原因是nginx配置里限制了上传文件的大小 client_m ...
- 【转】LiveWriter插入高亮代码插件介绍 基于SyntaxHighighter
转自:http://www.cnblogs.com/yaoshiyou/archive/2009/11/25/1610901.html 插件介绍 辛苦了两人小时写日志不小心浏览器崩溃了,发誓以后一定记 ...
- java多线程系类:基础篇:01基本概念:
这个系类的内容全部来源于http://www.cnblogs.com/skywang12345/p/3479024.html.特别在此声明!!! 本来想直接看那位作家的博客的,但还是复制过来. 多线程 ...
- css一些记录
比如右侧链接:更多 ,定义此span float:right ,但是 更多 要写在 短标题的左边 比如:<span>更多</span> <font>这是短标题 ...
- ZH奶酪:Java调用NLPIR汉语分词系统
NLPIR工具 支持自定义词表: 可以离线使用: 下载地址:http://ictclas.nlpir.org/newsdownloads?DocId=389 在线演示:http://ictclas.n ...
- 如何用 fiddler 代理调试本地手机页面
最近在做移动端的页面,但是移动端的调试很蛋疼.虽然说 90% 的功能都能用 chrome 下的模拟器来模拟解决,但是剩余的 10% 却只能在真机上调试.比如说一两个像素的误差,比如说只有真机上才能重现 ...
- 完全开源Android网络框架 — 基于JAVA原生的HTTP框架
HttpNet网络请求框架基于HttpUrlConnection,采用Client + Request + Call的请求模型,支持https默认证书,数字安全证书.支持http代理!后续将会实现队列 ...
- 记一次ASP.NET网站的入侵和如何避免被入侵
ASP.NET网站入侵第二波(LeaRun.信息化快速开发框架 已被笔者拿下) 详细介绍请看第二波 首先我要申明的是不是什么语言写出来的程序就不安全,而是得看写代码的人如何去写这个程序 前些日子我去客 ...
- CSS 问题集锦
[1]让DIV中的内容居中 1.文字垂直居中,关键代码:height:100px;line-height:100px(两个值要相等) <div style="margin:0 auto ...
- AngularJS引入Echarts的Demo
最近要用到图表展示,想了想,还是首选Echarts,HighCharts和D3.js备用吧, 而项目中也用到了AngularJS,所以需要把Echarts引入到AngularJs中一起使用, 试了试, ...