- 浏览: 51962 次
- 性别:
- 来自: 北京
文章分类
原文:http://www.oracle.com/technetwork/articles/javase/classloaders-140370.html
另外其它中文参考资料:http://www.iteye.com/topic/136427
Understanding Network Class Loaders
|
By Qusay H. Mahmoud , October 2004 |
|
When Java was first released to the public in 1995 it came with a web browser (HotJava), written in Java, that had the ability to automatically and dynamically download mini-applications (or applets) when it encountered the <Applet> tag in an HTML document. Such Applets are loaded on the fly across the network from remote web servers and run inside the browser's Java Virtual Machine (JVM). The mechanism that enabled such dynamic loading is a class loader, which is one of the cornerstones of Java dynamism. Class loaders are responsible for determining when and how classes can be added to a running Java environment, as well as making sure that important parts of the Java runtime environment are not replaced by impostor code.
The JVM default class loader knows how to load classes from the local file system, but what if you want to develop state-of-the-art applications that are capable of loading classes from remote servers? Class loaders can also be used to ensure safety and security of byte codes; for example, you can develop a custom class loader capable of checking a digital signature before executing untrusted foreign code.
This article provides a tutorial on network class loaders, and:
- Discusses the class loader mechanism
- Offers a flavor of the effort involved in developing network class loaders
- Discusses the security issues surrounding network class loaders
- Shows how to protect network class loaders from loading malicious code
Applications written in statically compiled programming
languages, such as C and C++, are compiled into native, machine-specific
instructions and saved as an executable file. The process of combining
the code into an executable native code is called
linking
- the merging of separately compiled code
with shared library code to create an executable application. This is
different in dynamically compiled programming languages such as Java. In
Java, the
.class
files generated by the Java compiler
remain as-is until loaded into the Java Virtual Machine (JVM) -- in
other words, the linking process is performed by the JVM at runtime.
Classes are loaded into the JVM on an 'as needed' basis. And when a
loaded class depends on another class, then that class is loaded as
well.
When a Java application is launched, the first class to run (or the entry point into the application) is the one with
public static void
method called
main()
. This class usually has references to
other classes, and all attempts to load the referenced classes are
carried out by the class loader.
To get a feeling of this recursive class loading as well as the class loading idea in general, consider the following simple class:
public class HelloApp { public static void main(String argv[]) { System.out.println("Aloha! Hello and Bye"); } } |
If you run this class specifying the
-verbose:class
command-line option, so that
it prints what classes are being loaded, you will get an output that
looks as follows. Note that this is just a partial output since the list
is too long to show here.
prmpt>
java -verbose:class HelloApp
[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]
|
As you can see, the Java runtime classes required by the application class (
HelloApp
) are loaded first.
The Java programming language keeps evolving to make the life of applications developers easier everyday. This is done by providing APIs that simplify your life by allowing you to concentrate on business logic rather than implementation details of fundamental mechanisms. This is evident by the recent change of J2SE 1.5 to J2SE 5.0 in order to reflect the maturity of the Java platform.
As of JDK 1.2, a bootstrap class loader that is built into the JVM is responsible for loading the classes of the Java runtime. This class loader only loads classes that are found in the boot classpath, and since these are trusted classes, the validation process is not performed as for untrusted classes. In addition to the bootstrap class loader, the JVM has an extension class loader responsible for loading classes from standard extension APIs, and a system class loader that loads classes from a general class path as well as your application classes.
Since there is more than one class loader, they are represented in a tree whose root is the bootstrap class loader. Each class loader has a reference to its parent class loader. When a class loader is asked to load a class, it consults its parent class loader before attempting to load the item itself. The parent in turn consults its parent, and so on. So it is only after all the ancestor class loaders cannot find the class that the current class loader gets involved. In other words, a delegation model is used.
The
java.lang.ClassLoader
is an abstract class
that can be subclassed by applications that need to extend the manner in
which the JVM dynamically loads classes. Constructors in
java.lang.ClassLoader
(and its subclasses)
allow you to specify a parent when you instantiate a new class loader.
If you don't explicitly specify a parent, the virtual machine's system
class loader will be assigned as the default parent. In other words, the
ClassLoader
class uses a delegation model to search for classes and resources. Therefore, each instance of
ClassLoader
has an associated parent class
loader, so that when requested to find a class or resources, the task is
delegated to its parent class loader before attempting to find the
class or resource itself. The
loadClass()
method of the
ClassLoader
performs the following tasks, in order, when called to load a class:
- If a class has already been loaded, it returns it.
- Otherwise, it delegates the search for the new class to the parent class loader.
- If the parent class loader doesn't find the class,
loadClass()
calls the methodfindClass()
to find and load the class.
The
finalClass()
method searches for the class in the current class loader if the class wasn't found by the parent class loader.
Developing your own class loaders is an inherently
dangerous undertaking as this can cause no end of security trouble. For
this reason, the Java 2 platform has added useful classes to the core
APIs in order to make developing and using class loaders easier than
ever. For example, the
java.security.SecureClassLoader
class extends the
ClassLoader
with additional support for
defining classes with an associated code source and permissions which
are retrieved by the system policy by default.
The
java.net.URLClassLoader
class, which is a subclass of
SecureClassloader
, can be easily used to load
classes and resources from a search path of URLs referring to
directories and JAR files. The URLs will be searched in the order
specified for classes and resources after first searching in the parent
class loader.
The
URLClassLoader
can be used to easily develop
an application capable of loading classes and resources from remote
servers. First, you need to define the URLs to be searched for classes.
Any URL that ends with a '
/
' is assumed to refer to a directory,
otherwise the URL is assumed to refer to a JAR file which will be opened
as needed. Once an instance of the
URLClassLoader
is constructed, the
loadClass(String name)
method of the
ClassLoader
class is used to load the class
with the specified name. Once a class has been loaded, an instance can
be created (this means that the constructor will be invoked). Code
Sample 1 shows a sample implementation. Note, however, that it is
recommended to override and use the
findClass()
method instead.
import java.net.*; import java.io.*; public class MyLoader { public static void main (String argv[]) throws Exception { URLClassLoader loader = new URLClassLoader(new URL[] { new URL("http://www.javacourses.com/classes/") }); // Load class from class loader. argv[0] is the name of the class to be loaded Class c = loader.loadClass (argv[0]); // Create an instance of the class just loaded Object o = c.newInstance(); } } |
Tester
class, which is shown in Code Sample 2, has been compiled and the
Tester.class
has been uploaded to
www.javacourses.com/classes
.
public class Tester { public Tester () { System.out.println ("Hello there"); } public static void main(String argv[]) { System.out.println("Network Class Loaders"); } } |
Now, you can run
MyLoader
as follows:
prompt>
java MyLoader Tester
|
This will load the
Tester.class
class from the
http://www.javacourses.com/classes/
, and as a result the output will be:
Hello there
When an object is instantiated, the class's constructor was called. In other words, the
main()
method wasn't invoked. We will see how to do that shortly.
The
URLClassLoader
is flexible and is capable of loading classes from a JAR file. To experiment with this, create a JAR file (
test.jar
) that contains the
Tester.class
as follows:
prompt>
jar cf test.jar Tester.class
|
The
test.jar
is already available at
http://www.javacourses.com/classes/test.jar
, so to test the code, change the URL in Code Sample 1 to read
http://www.javacourses.com/classes/test.jar
, then compile the code and run it as before and you will see the same results.
java.lang.reflect
) can be used to dynamically
figure out the capabilities of an object without necessarily knowing
anything about it in advance. As an example, the reflection APIs can be
used to invoke the
main()
method of the loaded class. Code Sample 3 shows a sample implementation.
import java.net.*; import java.io.*; import java.lang.reflect.*; public class MyLoader2 { public static void main (String argv[]) throws Exception { URLClassLoader loader = new URLClassLoader(new URL[] { new URL("http://www.javacourses.com/classes/") }); // Load class from class loader. argv[0] is the name of the class to be loaded Class c = loader.loadClass (argv[0]); Method m = c.getMethod("main", new Class[] {argv.getClass() }); m.setAccessible(true); int mods = m.getModifiers(); if(m.getReturnType() != void.class || !Modifier.isStatic(mods) || !Modifier.isPublic(mods)) { throw new NoSuchMethodException("main"); } try { m.invoke(null, new Object[] { argv }); } catch(IllegalAccessException e) { } } } |
Compile and run the example as shown earlier. The output will be:
Network Class Loaders
which is the message printed by the
main()
method.
Since the above application,
MyLoader2
, is capable of loading arbitrary
classes from a network then your system (local disk) is at risk. Those
arbitrary classes get interpreted by the class loader into the JVM,
which means that the byte codes -- no matter how malicious -- will be
interpreted in your system. To demonstrate just one kind of malicious
code, consider the following example.
Imagine for a moment that someone is aware of a sensitive file, with the name
personal-data.txt
, on your machine. That
someone may write a simple application to delete that file from your
system, or even to email a copy of it across the network -- perhaps by
inviting you to download an "interesting" class of byte codes. The
simple application would resemble that shown here:
import java.io.File; public class MaliciousApp { public static void main(String argv[]) { try { File file = new File("personal-data.txt"); if(file.delete() == true) { System.out.println("File: "+ file + " has been deleted!"); } else { System.out.println("Cannot delete file!"); } } catch(Exception e) { System.out.println("Exception: "+e.getMessage()); } } } |
If your enemy compiled the class and asked you to load it (
java MyLoader2 MaliciousApp
), this code would delete the file
personal-data
from your system. This is just
one example of security concerns associated with class loaders; try to
think of others. For example, what happens if an application is able to
load its own class loader, or open socket connections to remote hosts?
These are actually some of the security issues that applets (and
therefore class loaders implemented by web browsers) are concerned with.
You may ask, but wouldn't the Java environment protect against such malicious code? Built-in safety mechanisms ensure that the system is not subverted by invalid code, but not malicious code.
One way to protect against such attacks is by using a security manager, which is not automatically installed when an application is running. If you wish to apply the same security policy to an application found on the local file system as to downloaded applets, you can invoke the Java interpreter with the default security manager as follows:
prompt>
java -Djava.security.manager MyLoader2
|
This, however, will give you the following output. As you can see an
AccessControlException
is thrown.
Exception in thread "main" java.security.AccessControlException: access denied ( java.lang.RuntimePermission createClassLoader) at java.security.AccessControlContext.checkPermission(Unknown Source) at java.security.AccessController.checkPermission(Unknown Source) at java.lang.SecurityManager.checkPermission(Unknown Source) at java.lang.SecurityManager.checkCreateClassLoader(Unknown Source) at java.lang.ClassLoader.<init>(Unknown Source) at java.security.SecureClassLoader.<init>(Unknown Source) at java.net.URLClassLoader.<init>(Unknown Source) at MyLoader.main(MyLoader.java:8) |
Now, since there is a security manager in place, the
URLClassLoader
constructor will first call the security manager's
checkCreateClassLoader()
to ensure creation
of a class loader is allowed. The default security manager, however,
doesn't allow your application to create its own class loader. One
possible solution is to define a security policy. The Java environment
will adhere to run-time restrictions; therefore, you can devise an
application-level security policy for use with your application. Such a
security policy allows you to state, using
grant
clauses, what sorts of actions a Java
program can and cannot perform. Code Sample 4 shows a sample security
policy that allows code loaded from the local file system to do
anything. Using this policy, the application is allowed to create its
own class loader. A security policy can be specified on the command line
using the
-Djava.security.policy=
policy-name
command line argument.
grant codeBase "file:/-" { permission java.security.AllPermission; }; |
The application can now be run as follows:
prompt>
java -Djava.security.manager -Djava.security.policy=policy.txt MyLoader2 MaliciousApp
|
As you can see, both the default security manager as
well as the security policy are being enforced. This means that local
code can do everything (as defined by the
AllPermission
in
policy.txt
, but remote code is still being
checked by the default security policy, which means that remote code
cannot open local files among other things.
The output of the previous command will be:
Exception: access denied (java.io.FilePermission personal-data.txt delete)
As you can see, an exception is thrown when the loaded class,
MaliciousApp
, tries to delete a local file.
URLClassLoader
, check out the
JarRunner
application, which enables you to run an application that's bundled in a
JAR file by specifying the JAR file's URL on the command line.
The Java 2 platform also introduced the notion of context class loader. A thread's context class loader is, by default, set to the context class loader of the thread's parent. The hierarchy of threads is rooted at the primordial thread (the one that runs the program). The context class loader of the primordial thread is set to the class loader that loaded the application. The thread's context class loader will be the application's class loader. This loader is used by the Java runtime in the Java Remote Method Invocation (RMI) to load classes on behalf of the user application. The thread's context class loader can be easily changed as follows:
String url = "some URL; ClassLoader previous = Thread.currentThread().getContextClassLoader(); // Create a class loader using the URL as the codebase // Use previous as parent class loader to maintain current visibility ClassLoader current = URLClassLoader.newInstance(new URL[]{new URL(url)}, previous); Thread.currentThread().setContextClassLoader(current); |
发表评论
-
xms xmx
2011-06-13 17:45 784Xmx是java的一个选项,用来设置你的应用程序能够使用的最大 ... -
将 Java Web 应用从 Windows 移植到 AIX 时需要注意的问题
2011-06-01 12:52 655http://www.ibm.com/developerwor ... -
java security
2011-05-25 17:07 732一些笔记来自《Chapter 3 ... -
线程笔记
2011-05-22 18:54 685Chapter 20 of Inside the Java V ... -
java自带的打印API
2011-05-13 11:43 692官方手册 http://java.sun.com/produ ... -
一段怪程序段
2011-05-12 21:26 712String astr = "hello" ... -
垃圾回收器研究
2011-05-07 23:11 685《Inside the Java Virtual Machin ... -
Generics and arrays
2011-05-06 12:35 696转自:http://weblogs.java.net/blog ... -
class 文件结构
2010-12-22 14:53 714官方讲解网址:http://java.sun.com/docs ... -
现阶段对ClassLoader的困惑
2010-12-22 11:33 7701.由于CLASSLOADER是DELEGATE模式,加载一个 ... -
Apache Harmony介绍
2010-12-22 10:02 932从以下网址可得个详细的了解: http://www.ibm.c ... -
java nio
2010-12-11 10:34 752注:转自http://www.iteye.com/topic/ ... -
两份JVM学习资料
2010-12-06 16:07 951慢慢琢磨jvm.pdf: ...
相关推荐
tables-3.6.1-cp39-cp39-win_amd64.whl
基于springboot大学生心理咨询平台源码数据库文档.zip
基于Java web 实现的仓库管理系统源码,适用于初学者了解Java web的开发过程以及仓库管理系统的实现。
基于springboot智能推荐旅游平台源码数据库文档.zip
内容概要:本文是一份详尽的Ruby语言教程,首先介绍了Ruby语言的基本信息和发展背景。接着详细讲解了Ruby的基础语法,如变量、数据类型、运算符、控制流等,并深入探讨了面向对象编程的关键概念,包括类、对象、继承、封装和多态。随后介绍了Ruby的一些高级特性,如模块、异常处理、迭代器和文件I/O操作。最后,讨论了Ruby在Web开发中的应用,尤其是与Rails框架的结合。每个部分都配有相应的代码示例,帮助读者更好地理解和实践。 适合人群:适用于初学者和有一定基础的程序员,特别是对Ruby语言感兴趣的人。 使用场景及目标:学习和掌握Ruby语言的各项基础知识和高级特性,为进一步进行Web开发或其他相关编程打下坚实的基础。 其他说明:教程中的每一部分内容都有详细的解释和代码示例,非常适合自学和教学使用。
GEE训练教程——Landsat5、8和Sentinel-2、DEM和各2哦想指数下载
基于springboot在线问诊系统源码数据库文档.zip
基于springboot的流浪猫狗救助系统源码数据库文档.zip
GEE训练教程
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
本教程帮助您了解什么是 SQLite,它与 SQL 之间的不同,为什么需要它,以及它的应用程序数据库处理方式。需要的朋友们可以参考看看! SQLite是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite是一个增长最快的数据库引擎,这是在普及方面的增长,与它的尺寸大小无关。SQLite 源代码不受版权限制。 什么是 SQLite? SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,您不需要在系统中配置。 就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。 为什么要用 SQLite? 不需要一个单独的服务器进程或操作的系统(无服务器的)。 SQLite 不需要配置,这意味着不需要安装或管理。 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。 SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250K
基于springboot学生选课系统源码数据库文档.zip
【Android UI】SurfaceView中使用 Canvas 绘制可缩放大图 ( 拖动和缩放相关的变量 | Canvas 绘图函数 | 手势识别 多点触控流程 | 拖动图片 | 缩放图片 ) 博客链接:https://blog.csdn.net/shulianghan/article/details/143950948 一、需求分析 和 核心要点 说明 1、需求说明 2、核心要点 - 拖动和缩放相关的变量 3、核心要点 - Canvas 绘图函数 4、核心要点 - 手势识别 多点触控流程 5、核心要点 - 拖动图片 6、核心要点 - 缩放图片 二、完整代码示例 1、环境说明 2、SurfaceView 完整代码 3、运行结果
基于springboot+web的二手闲置交易系统源码数据库文档.zip
GEE训练教程
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
基于SpringBoot的宠物寄领养网站源码数据库文档.zip
基于springboot的电影院售票管理系统源码数据库文档.zip
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
数据存放网盘,txt文件内包含下载链接及提取码,永久有效。失效会第一时间进行补充。样例数据及详细介绍参见文章:https://blog.csdn.net/T0620514/article/details/143956923