今天遇到一个奇怪的现象,我把环境变量里的classpath删除掉之后仍然可以执行java程序(path属性没有删除)。
后来终于明白了,这是java的类加载顺序支配的。
java虚拟机加载一个类分为以下三种顺序:
1:Bootstrap 2:Extension 3:Users
一: Bootstrap:在java启动时载入的类,主要是一些重要的jdk的jar文件。比如rt.jar。这个jar文件包含了jdk的一些基础类库,比如我们熟知的java.lang,java.util等等都包含在rt.jar文件里。这个文件是Bootstrap负责加载的,也就是说我们不需要在项目中手动导入这个jar文件,也不需要在classpath里将他添加进去(他的实际目录为%JAVA_HOME%\jre\bin\rt.jar)。所以就可以解释我遇到的那个奇怪的问题了。没有classpath,一些基本的程序还是可以运行的。当然,Bookstrap不止装载rt.jar一个jar文件。要想知道他都加载了哪些类,可以用如下方法打印:System.out.println(System.getProperty("sun.boot.class.path"));。打印结果如下:
C:\Program Files\Java\jdk1.6.0_05\jre\lib\resources.jar;C:\Program Files\Java\jd
k1.6.0_05\jre\lib\rt.jar;C:\Program Files\Java\jdk1.6.0_05\jre\lib\sunrsasign.ja
r;C:\Program Files\Java\jdk1.6.0_05\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.
6.0_05\jre\lib\jce.jar;C:\Program Files\Java\jdk1.6.0_05\jre\lib\charsets.jar;C:
\Program Files\Java\jdk1.6.0_05\jre\classes
也就是说,在java启动的时候就已经加载了这么多的类。只要你的程序引用到的类都在这些jar文件里有的话,那就不需要设置什么classpath,更不手动需要导入jar包。
二:Extension:如果在Bootstrap的路径里找不到所要的类怎么办?那么这时java虚拟机就会去ext目录下找。具体的目录为%JAVA_HOME%\jre\lib\ext。我们可以试验一下。在ext目录里有一个dt.jar,里面有一个类:javax.swing.BoxBeanInfo。如果我们尝试去加载这个类,按照加载顺序,它会去ext目录下找。看一个程序:
public class tet{
public static void main(String[] args)throws ClassNotFoundException
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class lo = loader.loadClass("javax.swing.BoxBeanInfo");
System.out.println(lo.getClassLoader());
}
}
它的打印结果是:sun.misc.Launcher$ExtClassLoader@addbf1,很明显,他是由ExtClassLoader类加载器进行加载的。因为如果是Bootstrap加载的类,在打印它的类加载器的时候会是null。
三:Users :如果所需要的类在以上的目录里都没有,比如你想要一个spring的BeanFactory类,那JDK本身是不可能带的,所以必须由外部导入。由外部导入又有好几种方法,但是java虚拟机的搜索顺序是:
1:默认的User classes . (dot) 就是指当前目录。
2:系统变量 CLASSPATH 所指定的类库,该变量覆盖(override)默认的User classes。
3:用命令行参数 -cp 或 -classpath指定的类库。这个时候覆盖默认的User classes 和CLASSPATH变量。
4:通过-jar 参数指定的jar文件。此时覆盖上面的三种情况,如果使用这种情况,所有的类文件必须来自指定的jar 文件
由此可见,我们平时将一个jar文件放到当前工程的lib目录下,就是第一种搜索顺序,所以如果你不嫌麻烦,完全可以将他设置到classpath之下,当然我们实际不会这么干。此时如果我们打印它的类加载器就应该是ApplicationClassLoader。
另外需要说明的是:ApplicationClassLoader的父加载器是ExtClassLoader,ExtClassLoader的父加载器是Bootstrap。但是,打印Bootstrap的类的加载器的的时候往往显示null,好像没有一样,其实打印null就表示是Bootstrap。另外,java的类加载是采用委托机制,即遇到一个类要加载,它不会用子加载器进行加载,而是将请求上述到父加载器,如果父加载器没有找到,就再上述到更高一级的父加载器,一直到Bootstrap为止。如果没有找到,就按照刚才的路径往下转。直到找到为止。所以,如果一个类在classpath里有,在Ext目录下也有,那么加载他的类加载器一定是ExtClassLoader。
我们再来看上面的那个程序:
public class tet{
public static void main(String[] args)throws ClassNotFoundException
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class lo = loader.loadClass("javax.swing.BoxBeanInfo");
System.out.println(lo.getClassLoader());
}
}
这次我们将在ext目录下的dt.jar文件剪切掉,将他放到%JAVA_HOME%\lib目录下,并且将他设置到classpath环境变量里面。这次我们再打印的话,结果为:sun.misc.Launcher$AppClassLoader@19821f,他的类加载器显然已经变了。这就证明了在classpath里的类是有ApplicationClassLoader加载的,他属于用户自己的类。
分享到:
相关推荐
在Java中,类加载器负责查找并加载类到Java虚拟机中。我们可以通过自定义类加载器来实现热加载。例如,`MemoryClassLoader.java`可能就是一个自定义类加载器的实现,它可以在内存中动态加载或更新类。 **JarinJAR**...
在Java中,类加载器(Class Loader)是一项核心机制,用于将字节码(.class文件)加载到JVM中,使其成为运行时的对象。类加载器不仅实现了类的加载功能,还确保了Java程序在多线程环境中的安全性和隔离性。类加载器...
"Java 中类加载过程全面解析" Java 中类加载过程是 Java 语言中一个非常重要的机制,它负责将类文件加载到内存中,以便 JVM 可以使用这些类。类加载过程是一个复杂的过程,涉及到多个步骤和机制。下面将对 Java 中...
它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java Applet 需要从远程下载 Java 类文件到浏览器中并执行。现在类加载器在 ...
Java类加载器是Java虚拟机(JVM)的关键组成部分,它负责查找并加载类到内存中,使得程序能够运行。自定义Java类加载器允许我们根据特定需求扩展默认的加载机制,例如,从非标准位置加载类或者实现动态加载。在Java...
Java 类加载器是Java虚拟机(JVM)的核心组成部分,它负责将编译后的字节码文件(.class文件)加载到JVM中并转换为运行时的数据结构。Tomcat,作为广泛使用的Java Servlet容器,它自定义了一套类加载机制,以满足Web...
Java 类加载器是Java虚拟机(JVM)的核心组成部分,它负责将类的字节码加载到内存中并转换为可执行的Java类。类加载器的作用不仅仅是加载类,还包括确保类的唯一性,避免重复加载,并且遵循特定的加载顺序。以下是对...
Java的类加载器是Java虚拟机(JVM)的核心组件之一,它负责将类的字节码从磁盘、网络或其他数据源加载到内存中,并转换为可执行的Java对象。类加载器不仅关乎程序的运行,还在实现动态加载、插件系统等方面发挥着...
类加载器是Java运行时环境的重要组成部分,负责加载类到JVM中,并确保类的正确加载与隔离。类加载器的基本结构如下: 1. **引导类加载器**(Bootstrap Class Loader):这是系统默认的类加载器,负责加载JRE/lib/rt...
在Java编程中,类动态加载是一项重要的技术,它允许程序在运行时根据需要加载新的类,从而提高了灵活性和可扩展性。这篇博客“Java类动态加载(一)——java源文件动态编译为class文件”可能主要探讨了如何在运行时...
Java类加载器是Java运行时环境的一个关键组成部分,负责将类文件(.class)从各种来源加载到JVM中。它不仅管理类的生命周期,还确保了类的正确加载和初始化,是Java动态特性的基石。 #### 类加载器的工作原理 Java...
Java中的类加载器是JVM(Java虚拟机)的核心组件之一,它们负责将.java源代码编译成的.class字节码文件加载到JVM中,从而使得程序能够运行。类加载器不仅涉及到程序的正常执行,还与Java的动态加载、模块化系统以及...
Java中的类加载器遵循一个原则叫做“父母委托模型”,即当一个类加载器收到类加载请求时,首先将加载任务委托给父类加载器,只有当父类加载器无法完成加载时才会尝试自己加载。 这种设计模式的好处在于避免了类的...
传统的Java应用程序在启动时,由JVM(Java虚拟机)通过类加载器将类加载到内存中,一旦加载完成,除非程序退出,否则这些类通常不会被重新加载。然而,在开发过程中,我们可能希望在不重启应用的情况下,对已加载的...
Java应用程序类加载器是Java平台的核心组成部分之一,它负责加载应用程序中的类到JVM(Java虚拟机)中,使得程序能够执行。理解类加载器的工作原理对于深入学习Java编程至关重要。在Java中,类加载器按照层次结构...
Java 类加载器是Java运行时环境的一个重要组成部分,它的主要职责是将编译后的字节码(.class文件)加载到JVM中,使得程序能够运行。类加载器的机制保证了类的唯一性,同时也提供了灵活性,允许我们自定义加载逻辑。...
线程上下文类加载器(Thread Context ClassLoader)则是在特定线程中使用的类加载器,主要用于解决一些应用服务器中类加载的复杂问题,如J2EE容器中的类加载需求。 总的来说,理解Java类加载机制对于排查类加载错误...