关键词:
java的类加载机制
前言
学生时代应抱着问题去学习一门语言,例如:在学习java语言的过程中,我遇到过java主方法main里面参数到底是存的什么?还有java语言的Object是如何成为所有类的父类的?java虚拟机到底如何解析字节码文件的?java是纯面向对象编程语言那么它的类是怎样的加载过程?今天我就带着大家一探究竟。
步入正题
首先我们都熟悉DOS界面去执行我们编写的源码,第一步使用javac xxx.java命令,这个命令其实就是调用java的编译器,每一门语言都有自己的编译器,有的源文件是可以直接编译为可执行文件。但是java的编译器只能将源码编译成二进制的字节码文件xxx.class,最后在由java命令调用JVM(java虚拟机)。当我们要使用某个类时,虚拟机就会去加载它的字节码文件,并创建对应的对象,把class文件加载到JVM内存的过程就是类的加载过程。
类的加载过程:
1.加载
加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的 java.lang.Class 对
象,作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个 Class 文件获取,这里既
可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取),也可以在运行时计算生成(动态代理),
也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类)。
2.验证
这一阶段的主要目的是为了确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求,并
且不会危害虚拟机自身的安全。
3.准备
准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使
用的内存空间。注意这里所说的初始值概念,比如一个类变量定义为:
public static int v = 8080;
实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080,将 v 赋值为 8080 的 put static 指令是
程序被编译后,存放于类构造器方法之中。
但是注意如果声明为:
public static final int v = 8080;
在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v
赋值为 8080。
4.解析
解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中
的:CONSTANT_Class_info、CONSTANT_Field_info、CONSTANT_Method_info等类型的常量。
符号引用: 与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟
机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引
用的字面量形式明确定义在 Java 虚拟机规范的 Class 文件格式中。
直接引用: 可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有
了直接引用,那引用的目标必定已经在内存中存在。
5.初始化
初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载
器以外,其它操作都由 JVM 主导。到了初始阶段,才开始真正执行类中定义的 Java 程序代码。
初始化阶段是执行类构造器
<client>
方法的过程。<client>
方法是由编译器自动收集类中的类变
量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证子<client>
方法执行之前,父类
的<client>
方法已经执行完毕,如果一个类中没有对静态变量赋值也没有静态语句块,那么编译
器可以不为这个类生成<client>()
方法。
以下6种情况不会执行类的初始化
- 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
- 定义对象数组,不会触发该类的初始化。
- 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触
发定义常量所在的类。 - 通过类名获取 Class 对象,不会触发类的初始化。
- 通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初
始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。 - 通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作。
类加载器
以上类的加载过程肯定离不开java的类加载器,接下来我们谈谈类加载器,虚拟机设计团队把加载动作放到 JVM 外部实现,以便让应用程序决定如何获取所需的类,JVM 提供了 3 种类加载器:
1.启动类加载器Bootstrap ClassLoader
负责加载 JAVA_HOME\\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被虚拟机认可(按文件名识别,如 rt.jar)的类。
2.扩展类加载器(Extension ClassLoader)
负责加载 JAVA_HOME\\lib\\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。
3.应用程序类加载器(Application ClassLoader)
负责加载用户路径(classpath)上的类库。JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader实现自定义的类加载器。
双亲委派: 在应用程序类加载器中采用了双亲委派机制,如果一个程序需要加载一个类时,此类并不会立马就去执行加载器,而是先去执行父类的类加载器,如果父类还有父类的话,会层层往上执行,如果发现父类的类加载器并不能运行加载的话,在由本类去加载。
当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父
类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,
只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的
Class),子类加载器才会尝试自己去加载。
采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载
器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载
器最终得到的都是同样一个 Object 对象。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
synchronized (getClassLoadingLock(name))
// First, check if the class has already been loaded
// 如果 Java 虚拟机已将此加载器记录为具有给定二进制名称的某个类的启动加载器,
//则返回该二进制名称的类。
Class<?> c = findLoadedClass(name);
if (c == null)
long t0 = System.nanoTime();
try
if (parent != null)
c = parent.loadClass(name, false);//继续查找父类的类加载
else
c = findBootstrapClassOrNull(name);//返回启动类加载器加载的类
catch (ClassNotFoundException e)
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
if (c == null)
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
if (resolve)
resolveClass(c);
return c;
注意点:
1.loadClass()方法是ClassLoader类实现的,方法中的逻辑就是双亲委派机制
2.运行时加载自己指定的类,那么我们可以直接使用this.getClass().getClassLoder.loadClass(“className”),这样就可以直接调用ClassLoader的loadClass方法获取到class对象。
3.findClass(String name)
ClassLoader类中并没有实现findClass()方法的具体代码逻辑,取而代之的是抛出ClassNotFoundException异常
4.defineClass(byte[] b, int off, int len)
使用可选的 ProtectionDomain 将 ByteBuffer 转换为 Class 类的实例。如果该域为 null,则将默认域分配给 defineClass(String, byte[], int, int) 的文档中指定的类。这个类必须分析后才能使用。
有关包中定义的第一个类(它确定了包的证书集合)的规则,以及对类名称的限制,都与 defineClass(String, byte[], int, int, ProtectionDomain) 的文档中指定的相同。
调用形式为 cl.defineClass(name, bBuffer, pd) 的此方法所产生的结果与以下语句产生的结果相同 ,注意的是,如果直接调用defineClass()方法生成类的Class对象,这个类的Class对象并没有解析(也可以理解为链接阶段,毕竟解析是链接的最后一步),其解析操作需要等待初始化阶段进行。
protected Class<?> findClass(String name) throws ClassNotFoundException
// 获取类的字节数组
byte[] classData = getClassData(name);
if (classData == null)
throw new ClassNotFoundException();
else
//使用defineClass生成class对象
return defineClass(name, classData, 0, classData.length);
5.URLClassLoader
在创建URLClassPath对象时,会根据传递过来的URL数组中的路径判断是文件还是jar包,即拓展类加载器ExtClassLoader和系统类加载器AppClassLoader,这两个类都继承自URLClassLoader,是sun.misc.Launcher的静态内部类。sun.misc.Launcher主要被系统用于启动主应用程序,ExtClassLoader和AppClassLoader都是由sun.misc.Launcher创建的。
6.类加载器的关系
7.注意class文件的显示加载和隐式加载
JVM加载class文件到内存的方式,显示加载就是直接调用类加载器加载class文件,例如:Class.forName()
或者是this.getClass().getClassLoader().loadClass()
加载class对象。隐式不会直接在代码里调用类加载器,而是通过虚拟机自动加载到内存中。
源码
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*/
package java.lang;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.CodeSource;
import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import java.util.Map;
import java.util.Vector;
import java.util.Hashtable;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import sun.misc.CompoundEnumeration;
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
/**
* A class loader is an object that is responsible for loading classes. The
* class <tt>ClassLoader</tt> is an abstract class. Given the <a
* href="#name">binary name</a> of a class, a class loader should attempt to
* locate or generate data that constitutes a definition for the class. A
* typical strategy is to transform the name into a file name and then read a
* "class file" of that name from a file system.
*
* <p> Every @link Class <tt>Class</tt> object contains a @link
* Class#getClassLoader() reference to the <tt>ClassLoader</tt> that defined
* it.
*
* <p> <tt>Class</tt> objects for array classes are not created by class
* loaders, but are created automatically as required by the Java runtime.
* The class loader for an array class, as returned by @link
* Class#getClassLoader() is the same as the class loader for its element
* type; if the element type is a primitive type, then the array class has no
* class loader.
*
* <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to
* extend the manner in which the Java virtual machine dynamically loads
* classes.
*
* <p> Class loaders may typically be used by security managers to indicate
* security domains.
*
* <p> The <tt>ClassLoader</tt> class uses a delegation model to search for
* classes and resources. Each instance of <tt>ClassLoader</tt> has an
* associated parent class loader. When requested to find a class or
* resource, a <tt>ClassLoader</tt> instance will delegate the search for the
* class or resource to its parent class loader before attempting to find the
* class or resource itself. The virtual machine's built-in class loader,
* called the "bootstrap class loader", does not itself have a parent but may
* serve as the parent of a <tt>ClassLoader</tt> instance.
*
* <p> Class loaders that support concurrent loading of classes are known as
* <em>parallel capable</em> class loaders and are required to register
* themselves at their class initialization time by invoking the
* @link
* #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>
* method. Note that the <tt>ClassLoader</tt> class is registered as parallel
* capable by default. However, its subclasses still need to register themselves
* if they are parallel capable. <br>
* In environments in which the delegation model is not strictly
* hierarchical, class loaders need to be parallel capable, otherwise class
* loading can lead to deadlocks because the loader lock is held for the
* duration of the class loading process (see @link #loadClass
* <tt>loadClass</tt> methods).
*
* <p> Normally, the Java virtual machine loads classes from the local file
* system in a platform-dependent manner. For example, on UNIX systems, the
* virtual machine loads classes from the directory defined by the
* <tt>CLASSPATH</tt> environment variable.
*
* <p> However, some classes may not originate from a file; they may originate
* from other sources, such as the network, or they could be constructed by an
* application. The method @link #defineClass(String, byte[], int, int)
* <tt>defineClass</tt> converts an array of bytes into an instance of class
* <tt>Class</tt>. Instances of this newly defined class can be created using
* @link Class#newInstance <tt>Class.newInstance</tt>.
*
* <p> The methods and constructors of objects created by a class loader may
* reference other classes. To determine the class(es) referred to, the Java
* virtual machine invokes the @link #loadClass <tt>loadClass</tt> method of
* the class loader that originally created the class.
*
* <p> For example, an application could create a network class loader to
* download class files from a server. Sample code might look like:
*
* <blockquote><pre>
* ClassLoader loader = new NetworkClassLoader(host, port);
* Object main = loader.loadClass("Main", true).newInstance();
* . . .
* </pre></blockquote>
*
* <p> The network class loader subclass must define the methods @link
* #findClass <tt>findClass</tt> and <tt>loadClassData</tt> to load a class
* from the network. Once it has downloaded the bytes that make up the class,
* it should use the method @link #defineClass <tt>defineClass</tt> to
* create a class instance. A sample implementation is:
*
* <blockquote><pre>
* 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
* . . .
*
*
* </pre></blockquote>
*
* <h3> <a name="name">Binary names</a> </h3>
*
* <p> Any class name provided as a @link String parameter to methods in
* <tt>ClassLoader</tt> must be a binary name as defined by
* <cite>The Java™ Language Specification</cite>.
*
* <p> Examples of valid class names include:
* <blockquote><pre>
* "java.lang.String"
* "javax.swing.JSpinner$DefaultEditor"
* "java.security.KeyStore$Builder$FileBuilder$1"
* "java.net.URLClassLoader$3$1"
* </pre></blockquote>
*
* @see #resolveClass(Class)
* @since 1.0
*/
public abstract class ClassLoader
private static native void registerNatives();
static
registerNatives();
// The parent class loader for delegation
// Note: VM hardcoded the offset of this field, thus all new fields
// must be added *after* it.
private final ClassLoader parent;
/**
* Encapsulates the set of parallel capable loader types.
*/
private static class ParallelLoaders
private ParallelLoaders()
// the set of parallel capable loader types
private static final Set<Class<? extends ClassLoader>> loaderTypes =
Collections.newSetFromMap(
new WeakHashMap<Class<? extends ClassLoader>, Boolean>());
static
synchronized (loaderTypes) loaderTypes.add(ClassLoader.class);
/**
* Registers the given class loader type as parallel capabale.
* Returns @code true is successfully registered; @code false if
* loader's super class is not registered.
*/
static boolean register(Class<? extends ClassLoader> c)
synchronized (loaderTypes)
if (loaderTypes.contains(c.getSuperclass()))
// register the class loader as parallel capable
// if and only if all of its super classes are.
// Note: given current classloading sequence, if
// the immediate super class is parallel capable,
// all the super classes higher up must be too.
loaderTypes.add(c);
return true;
else
return false;
/**
* Returns @code true if the given class loader type is
* registered as parallel capable.
*/
static boolean isRegistered(Class<? extends ClassLoader> c)
synchronized (loaderTypes)
return loaderTypes.contains(c);
// Maps class name to the corresponding lock object when the current
// class loader is parallel capable.
// Note: VM also uses this field to decide if the current class loader
// is parallel capable and the appropriate lock object for class loading.
private final ConcurrentHashMap<String, Object> parallelLockMap;
// Hashtable that maps packages to certs
private final Map <String, Certificate[]> package2certs;
// Shared among all packages with unsigned classes
private static final Certificate[] nocerts = new Certificate[0];
// The classes loaded by this class loader. The only purpose of this table
// is to keep the classes from being GC'ed until the loader is GC'ed.
private final Vector<Class<?>> classes = new Vector<>();
// The "default" domain. Set as the default ProtectionDomain on newly
// created classes.
private final ProtectionDomain defaultDomain =
new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
null, this, null);
// The initiating protection domains for all classes loaded by this loader
private final Set<ProtectionDomain> domains;
// Invoked by the VM to record every loaded class with this loader.
void addClass(Class<?> c)
classes.addElement(c);
// The packages defined in this class loader. Each package name is mapped
// to its corresponding Package object.
// @GuardedBy("itself")
private final HashMap<String, Package> packages = new HashMap<>();
private static Void checkCreateClassLoader()
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkCreateClassLoader();
return null;
private ClassLoader(Void unused, ClassLoader parent)
this.parent = parent;
if (ParallelLoaders.isRegistered(this.getClass()))
parallelLockMap = new ConcurrentHashMap<>();
package2certs = new ConcurrentHashMap<>();
domains =
Collections.synchronizedSet(new HashSet<ProtectionDomain>());
assertionLock = new Object();
else
// no finer-grained lock; lock on the classloader instance
parallelLockMap = null;
package2certs = new Hashtable<>();
domains = new HashSet<>();
assertionLock = this;
/**
* Creates a new class loader using the specified parent class loader for
* delegation.
*
* <p> If there is a security manager, its @link
* SecurityManager#checkCreateClassLoader()
* <tt>checkCreateClassLoader</tt> method is invoked. This may result in
* a security exception. </p>
*
* @param parent
* The parent class loader
*
* @throws SecurityException
* If a security manager exists and its
* <tt>checkCreateClassLoader</tt> method doesn't allow creation
* of a new class loader.
*
* @since 1.2
*/
protected ClassLoader(ClassLoader parent)
this(checkCreateClassLoader(), parent);
/**
* Creates a new class loader using the <tt>ClassLoader</tt> returned by
* the method @link #getSystemClassLoader()
* <tt>getSystemClassLoader()</tt> as the parent class loader.
*
* <p> If there is a security manager, its @link
* SecurityManager#checkCreateClassLoader()
* <tt>checkCreateClassLoader</tt> method is invoked. This may result in
* a security exception. </p>
*
* @throws SecurityException
* If a security manager exists and its
* <tt>checkCreateClassLoader</tt> method doesn't allow creation
* of a new class loader.
*/
protected ClassLoader()
this(checkCreateClassLoader(), getSystemClassLoader());
// -- Class --
/**
* Loads the class with the specified <a href="#name">binary name</a>.
* This method searches for classes in the same manner as the @link
* #loadClass(String, boolean) method. It is invoked by the Java virtual
* machine to resolve class references. Invoking this method is equivalent
* to invoking @link #loadClass(String, boolean) <tt>loadClass(name,
* false)</tt>.
*
* @param name
* The <a href="#name">binary name</a> of the class
*
* @return The resulting <tt>Class</tt> object
*
* @throws ClassNotFoundException
* If the class was not found
*/
public Class<?> loadClass(String name) throws ClassNotFoundException
return loadClass(name, false);
/**
* Loads the class with the specified <a href="#name">binary name</a>. The
* default implementation of this method searches for classes in the
* following order:
*
* <ol>
*
* <li><p> Invoke @link #findLoadedClass(String) to check if the class
* has already been loaded. </p></li>
*
* <li><p> Invoke the @link #loadClass(String) <tt>loadClass</tt> method
* on the parent class loader. If the parent is <tt>null</tt> the class
* loader built-in to the virtual machine is used, instead. </p></li>
*
* <li><p> Invoke the @link #findClass(String) method to find the
* class. </p></li>
*
* </ol>
*
* <p> If the class was found using the above steps, and the
* <tt>resolve</tt> flag is true, this method will then invoke the @link
* #resolveClass(Class) method on the resulting <tt>Class</tt> object.
*
* <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override @link
* #findClass(String), rather than this method. </p>
*
* <p> Unless overridden, this method synchronizes on the result of
* @link #getClassLoadingLock <tt>getClassLoadingLock</tt> method
* during the entire class loading process.
*
* @param name
* The <a href="#name">binary name</a> of the class
*
* @parajava中的类加载机制(代码片段)
在Java虚拟机中,类在JVM中的生命周期为:加载、验证、准备、解析、初始化、使用和卸载几个阶段。一般类的主动加载会有以下情况:遇到new、getstatic、putstatic、或invokestatic这4条字节码(一般为new对象时,读... 查看详情
java中类加载机制(代码片段)
...码对象,那么这个字节码对象是由谁来产生的呢?java中的类是由谁来加载进内存的呢?接下来我介绍的就是负责将java中的字节码文件加载到内存,创建Class对象的类ClassLoader,也就是java中的类加载器。 类加载器一般由... 查看详情
tomcat的类加载机制(代码片段)
...类加载机制、双亲委派模型 文章中,我们介绍了JVM的类加载机制以及双亲委派模型,双亲委派模型的类加载过程主要分为以下几个步骤:(1)初始化ClassLoader时需要指定自己的parent是谁(2)先检查类... 查看详情
jvm的类加载机制(代码片段)
...终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。 类加载的规则:全盘负责,当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个... 查看详情
java技术专题深度分析加载器与双亲委派机制「入门篇」(代码片段)
加载器与双亲委派机制类加载器是怎么被创建出来的?什么是双亲委派机制?为什么要有这种机制?Class实例和类加载器究竟是在JavaHeap中,还是在方法区中?类加载器:可以实现通过一个类的全限定名称来获取... 查看详情
java序列化机制深度解析(代码片段)
概要序列化机制允许将实现序列化的Java对象转换为字节序列,这些字节序列可以被保存在磁盘上或通过网络传输,以备以后重新恢复原来的对象,序列化机制使得对象可以脱离程序的运行而独立存在可序列化的类包... 查看详情
mybatis源码学习(12)-资源加载(代码片段)
历史文章:Mybatis源码学习(11)-日志模块Mybatis中的资源加载依赖于JVM的类加载机制,在JVM中的类加载机制使用的双亲委派模式。默认情况下,JVM中存在三种加载器:BootstrapClassLoader、ExtensionClassLoader、SystemClassLoader... 查看详情
java中常见的类加载器及双亲委派机制的原理(代码片段)
...需要了解一下java中常见的几种类加载器。一、Java中常见的类加载器1.BootstrapClassLoader纯C++实现的类加载器,没有对应的Java类 查看详情
类加载机制(代码片段)
...了各种类加载器(那就是实现了 java.lang.ClassLoader 的类)。借助类加载器,容器的不同部分以及运行在容器上的Web应用就可以访问不同的仓库(保存着可使用的类和资源)。这个机制实现了Servlet规范2.4版(尤其是9.4节和9.... 查看详情
javasec类加载机制(代码片段)
这篇文章介绍java的类加载机制。Java是一个依赖于JVM(Java虚拟机)实现的跨平台的开发语言。Java程序在运行前需要先编译成class文件,Java类初始化的时候会调用java.lang.ClassLoader加载类字节码,ClassLoader会调用JVM的native方法(define... 查看详情
java反射机制学习:初始反射机制
本人小白一枚,想和大家一起分享我学习java的笔记和心得。 反射机制: 指的是可以于运行时加载、探知、使用编译期间完全未知的类。 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个已加载的类,... 查看详情
jvm类加载机制(代码片段)
...存等指定位置的资源。一个Java程序运行,至少有3个不同的类加载器实例,负责加载不同的类。这三个类加载器分别为,启动类加载器(BootstrapClassLoader),扩展类加载器(ExtensionClassLoader),应用程序类加载器(ApplicationClassLoade... 查看详情
双亲委派机制(代码片段)
...器)C++实现在java里无法获取负责加载<JAVA_HOME>/lib下的类ExtensionClassLoader(标准扩展类加载器)Java实 查看详情
从java的类加载机制谈起:聊聊java中如何实现热部署(热加载)(代码片段)
...,比如java.lang包中的相关类还是不能自定义一个同名的类来代替,主要因为JVM解析、验证class的时候,会进行相关判断。defineClass系统自带的ClassLoader,默认加载程序的是AppClassLoader,ClassLoader加载一个class,... 查看详情
java中常见的类加载器及双亲委派机制的原理(代码片段)
...需要了解一下java中常见的几种类加载器。一、Java中常见的类加载器1.BootstrapClassLoader纯C++实现的类加载器,没有对应的Java类,主要加载的是jre/lib/目录下的核心库2.ExtClassLoader类的全名是sun.misc.Launcher$ExtClassLoader... 查看详情
mybatis源码学习(12)-资源加载(代码片段)
历史文章:Mybatis源码学习(11)-日志模块Mybatis中的资源加载依赖于JVM的类加载机制,在JVM中的类加载机制使用的双亲委派模式。默认情况下,JVM中存在三种加载器:BootstrapClassLoader、ExtensionClassLoader、SystemClassLoader... 查看详情
探秘类加载器和类加载机制(代码片段)
在面向对象编程实践中,我们通过众多的类来组织一个复杂的系统,这些类之间相互关联、调用使他们的关系形成了一个复杂紧密的网络。当系统启动时,出于性能、资源利用多方面的考虑,我们不可能要求JVM一次性将全部的类... 查看详情
java双亲委派机制在android的应用(代码片段)
...8;按照文件名识别,如rt.jar、tools.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机的内存中。启动类加载器无法被Java程序直接引用,用户在编写自定义类加载器时,如果需要把加载... 查看详情