JavaSE--类加载器

参考:http://www.importnew.com/6581.html

Java 编译器会为虚拟机转换源指令。虚拟机代码存储在以 .class 为扩展名的类文件中,每个类文件都包含某个类或者接口的定义和代码实现。这些类文件必须由一个程序进行解释,该程序能够将虚拟机的指令集翻译成目标机器的机器语言。

虚拟机值加载程序执行时所需要的类文件。

 

类加载机制并非只使用单个的类加载器。每个 Java 程序至少拥有三个类加载器:

引导类加载器

扩展类加载器

系统类加载器(有时也称为应用类加载器)

引导类加载器负责加载系统类(通常从 JAR 文件 rt.jar 中进行加载)。它是虚拟机不可分割的一部分,而且通常是用 C 语言来实现的。引导类加载器没有对应的 ClassLoader 对象。

扩展类加载器用于从 jre/lib/ext 目录加载 “标准的扩展”。可以将 JAR 文件放入该目录,这样即使没有任何类路径,扩展类加载器也可以找到其中的各个类。

系统类加载器用于加载应用类。它在由 CLASSPATH 环境变量或者 -classpath 命令行选项设置的类路径中的目录里或者是 JAR/ZIP 文件里查找这些类。

在 Oracle 的 Java 语言实现中,扩展类加载器和系统类加载器都是用 Java 来实现的。它们都是 URLClassLoader 类的实例。

警告:如果将 JAR 文件放入 jre/lib/ext 目录中,并且在它的类中有一个类需要调用系统类或者扩展类,那么就会遇到麻烦。扩展类加载器并不使用类路径。

除了所有已经提到的位置,还可以从 jre/lib/endorsed 目录中加载类。这种机制只能用于将某个标准的 Java 类库替换为更新的版本(例如那些支持 XML 和 CORBA 的类)。

 

类加载器有一种父/子关系。除了引导类加载器外,每个类加载器都有一个父类加载器。根据规定,类加载器会为它的父类加载器提供一个机会,以便加载任何给定的类,并且只有在其父类加载器加载失败时,它才会加载该给定类。

某些程序具有插件架构,其中代码的某些部分是作为可选的插件打包的。如果插件被打包为 JAR 文件,那就可以直接用 URLClassLoader 类的实例去加载这些类。

 1 package classloader;
 2 
 3 import java.net.MalformedURLException;
 4 import java.net.URL;
 5 import java.net.URLClassLoader;
 6 
 7 public class URLDemo {
 8     
 9     public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
10         URL url= new URL("file:\\E:\\project_neon1\\Demo2\\commons-codec-1.9.jar");
11         URLClassLoader pluginLoader = new URLClassLoader(new URL[] {url});
12         Class<?> c1 = pluginLoader.loadClass("org.apache.commons.codec.binary.Base64");
13     }
14 
15 }

因为在 URLClassLoader 构造器中没有指定父类加载器,因此 pluginLoader 的父亲就是系统类加载器。

大多数时候,你不必操心类加载的层次结构。通常,类是由于其他的类需要它而被加载的,而这个过程对你是透明的。

偶尔,你也会需要干涉和指定类加载器。

考虑下面的例子:

你的应用的代码包含一个助手方法,它要调用 Class.forName(classNameString)。

这个方法是从一个插件类中被调用的。

而 classNameString 指定的正是一个包含在这个插件的 JAR 中类。

插件的作者很合理地期望这个类应该被加载。但是,助手方法的类是由系统类加载器加载的,这正式 Class.forName 所使用的类加载器。而对于它来说,在插件 JAR 中的类是不可视的,这种现象被称为类加载器倒置。

要解决这个问题,助手方法需要使用恰当的类加载器,它可以要求类加载器作为其一个参数传递给他。或者,它可以要求将恰当的类加载器设置成为当前线程的上下文类加载器。

每个线程都有一个对类加载器的引用,称为上下文类加载器。主线程的上下文类加载器是系统类加载器。当新线程创建时,它的上下文类加载器会被设置成为创建该线程的上下文类加载器。因此,如果你不做任何特殊的操作,那么所有线程就都将它们的上下文类加载器设置为系统类加载器。

可以通过下面的调用将上下文类加载器设置成为任何类加载器。

1 Thread t = Thread.currentThread();
2 t.setContextClassLoader(loader);

然后助手方法可以获取这个上下文类加载器:

1 Thread t = Thread.currentThread();
2 ClassLoader loader = t.getContextClassLoader();
3 Class cl = loaser.loadClass(className);

当上下文类加载器设置为插件类加载器时,问题依旧存在。应用设计者必须作出决策:通常,当调用由不同的类加载器加载的插件类的方法时,进行上下文类加载器的设置是一种好的思路;或者,让助手方法的调用者设置上下文类加载器。

如果你编写了一个按名字来加载类的方法,那么让调用者在传递显示的类加载器和使用上下文类加载器之间进行选择就是一种好的做法。不要直接使用该方法所属的类的类加载器。

 

在同一个虚拟机中,可以有两个类,它们的类名和包名都是相同的。类是由它的全名和类的加载器来确定的。这项技术在加载来自多处的代码时很有用。例如 servlets 和 EJB 的 “热部署”。

 

 

 

我们可以编写自己的用于特殊目的的类加载器,这使得我们可以在向虚拟机传递字节码之前执行定制的检查。

如果要编写自己的类加载器,只需要继承 ClassLoader 类,然后覆盖下面这个方法

findClass(String className)

ClassLoader 超类的 loadClass 方法用于将类的加载操作委托给其父类加载器去进行,只有当该类尚未加载并且父类加载器也无法加载该类时,才调用 findClass 方法。

如果要实现该方法,必须做到以下几点:

1) 为来自本地文件系统或者其他来源的类加载其字节码

2) 调用 ClassLoader 超类的 defineClass 方法,向虚拟机提供字节码

 

转载于:https://www.cnblogs.com/microcat/p/7150758.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429088.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下汇编语言学习笔记13 ---

这是17年暑假学习Linux汇编语言的笔记记录&#xff0c;参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译《汇编语言基于Linux环境》的书&#xff0c;喜欢看原版书的同学可以看《Assembly Language Step-By-Setp:Programming with Linux 3rd Edition》&#xff0c;非常感谢该…

java netbeans 教程_NetBeans 教程

NetBeans IDE Java 快速入门教程第一章本章通过指导您创建一个简单的 "Hello World" Java 控制台应用程序&#xff0c;简要介绍 NetBeans IDE 工作流。学习完本教程后&#xff0c;您将对如何在 IDE 中创建和运行应用程序有一个基本了解。学习完本教程所需的时间不到 …

几个python小程序

python小程序 1-100求和 1 def Sum(x, y):2 return xy3 print reduce(lambda x,y:xy,range(1,101))4 5 i 16 j 07 while i < 101:8 j i j9 i 1 10 print j View Code输出1-100之间的奇偶数1 i 1 2 a [] 3 while i < 100: 4 if i%2 0: 5 …

java输出a-z_有1-26个数字和a-z字母,用Java多线程实现先输出2和数字再输出2个字

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼public class Z extends Thread{char[] letters new char[]{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z};public static void main(String[] args){Z z new Z();X x new X();x.start();z.start();}public void run()…

Linux下git使用

一、安装 本人使用的是centos 7&#xff0c;首先安装git 1.下载git&#xff1a;wget https://Github.com/Git/Git/archive/v2.3.0.tar.gz 2.下载之后解压&#xff1a;tar xvf v2.3.0.tar.gz 3.进入解押文件目录&#xff1a;cd git-2.3.0 4.依次运行如下命令&#xff1a; ./conf…

java 水表识别_一种水表数字的AI智能识别方法与流程

本发明涉及模式识别与人工智能技术领域&#xff0c;特别涉及一种直观的水表数字的AI智能识别方法。背景技术&#xff1a;深度学习在目标检测的应用发展迅速&#xff0c;在YOLO(You Only Look Once)之后又出现了升级版本YOLOv2&#xff0c;采用的是Darknet-19作为基础网络&#…

Summary Day30

1.内存管理 1.1 进程中的内存区域划分 代码区 仅仅读常理区 全局区 BSS 堆 栈 1.2 字符串存储形式之间的比較 字符指针&#xff0c;字符数组。字符动态内存 1.3 虚拟内存管理技术 Unix/Linux系统总的内存都是採用虚拟内存管理技术进行管理。即&#xff1a;每一个…

java装箱和拆箱_java自动装箱和拆箱

这个是jdk1.5以后才引入的新的内容&#xff0c;作为秉承发表是最好的记忆&#xff0c;毅然决定还是用一篇博客来代替我的记忆&#xff1a;java语言规范中说道&#xff1a;在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱&#xff0c;解包装称为拆箱)&a…

java 插桩 工具_一个基于Eclipse的通用Java程序插桩工具.pdf

第38卷第7期 计算机科学 V01&#xff0e;38NO&#xff0e;7Science 20112011年7月 Computer July一个基于Eclipse的通用Java程序插桩工具郑晓梅(南京中医药大学信息技术学院 南京210046)(南京大学计算机软件新技术国家重点实验室 南京210093)摘要插桩技术作为一种有效理解程序动…

【FICO 汇率】汇率

汇率存储的表位TCURR 汇率维护的事务代码为&#xff1a;OB08 每一种货币汇率都有很多版本&#xff0c;按照时间有效性管理 汇率涉及的两种货币&#xff0c;第一个为从&#xff0c;第二个为到&#xff0c;一般换算比率都是1&#xff0c;但也有不是1的情况&#xff08;主要是换算…

java 新窗口跳转页面_Java web开发中页面跳转小技巧——跳转后新页面在新窗口打开...

最近学习Java web&#xff0c;在学习过程中想实现一个需求&#xff0c;就是在jsp页面跳转的时候&#xff0c;希望跳转后的新页面在新窗口中打开&#xff0c;而不是覆盖原来的页面&#xff0c;这个需求使我困惑了好长时间&#xff0c;后来通过大海捞针似的在网上寻找方法&#x…

分辨率到底是个什么概念?它和DPI之间是什么关系?

"分辨率"到底是个什么概念&#xff1f;它和DPI之间是什么关系&#xff1f; 分辨率&#xff1a;显示分辨率&#xff08;屏幕分辨率&#xff09;是屏幕图像的精密度&#xff0c;是指显示器所能显示的像素有多少。由于屏幕上的点、线和面都是由像素组成的&#xff0c;显…

mysql.w002_mysql简单例子

登陆数据库&#xff1a;mysql -u用户名 -p密码 -P端口 -h数据库地址‍‍‍‍‍‍修改mysql提示符&#xff1a;(仅本次连接有效)‍‍‍‍‍‍方法一&#xff1a;执行mysql -uroot -proot -prompt \h结果为&#xff1a;localhost方法二&#xff1a;进入mysql后&#xff0c;执行PR…

mysqli mysql的区别_phpmysqli和mysql区别详解

本文介绍下&#xff0c;php中有关mysqli与mysql类的一些区别&#xff0c;有需要的朋友&#xff0c;可以作个参考哦。一&#xff0c;PHP-MySQL 是 PHP 操作 MySQL 资料库最原始的 Extension &#xff0c;PHP-MySQLi 的 i 代表 Improvement &#xff0c;提更了相对进阶的功能。PD…

JQuery中的Deferred-详解和使用

首先&#xff0c;为什么要使用Deferred&#xff1f; 先来看一段AJAX的代码&#xff1a; 1 var data; 2 $.get(api/data, function(resp) { 3 data resp.data; 4 }); 5 doSomethingFancyWithData(data); View Code 这段代码极容易出问题&#xff0c;请…

ps aux grep java_linux命令ps-aux监控java进程

linux下用ps -aux可以监控java的进程情况。linux根据内核的不同对每个进程分配的最大使用内存不同&#xff0c;如果是32位机器&#xff0c;cpu最大的寻址空间是2的32次方&#xff0c;4G&#xff0c;但内核分配给每个进程最大的内存肯定是小于4G&#xff0c;经过重新编译的内核分…

【Eclipse】eclipse在线安装反编译插件

1.help->install new software 2.Add Name&#xff1a;jd-eclipse_update_site Location&#xff1a;http://jd.benow.ca/jd-eclipse/update 3.等待加载出来 4.持续点击下一步&#xff0c;直到完成。 转载于:https://www.cnblogs.com/flydkPocketMagic/p/7170283.html

java一维数组存入_java一维数组

1.通过数组名进行赋值&#xff0c;其实质是引用比如数组array1和数组array2若执行array2array1&#xff0c;实际上将array1的引用传递给array2&#xff0c;array1和array2 最后都指向同一个数组&#xff0c;array2原来引用的数组被回收。例如&#xff1a;int [] array1{1,2,3};…

Spring Boot 系列(一)快速入门

简介 Spring Boot是由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#xff0c;从而使开发人员不再需要定义样板化的配置。通过这种方式&#xff0c;Spring Boot致力于在蓬勃发展的快速应…

python代码编码成jni_python 设置文件编码格式的实现方法

如果要在python2的py文件里面写中文&#xff0c;则必须要添加一行声明文件编码的注释&#xff0c;否则python2会默认使用ASCII编码。(python3已经没有这个问题了&#xff0c;python3默认的文件编码是UTF-8)必须将编码注释放在第一行或者第二行,一般来说&#xff0c;Python文件的…