1.类的加载、连接和初始化
JVM和类
同一个JVM的所有线程、所有变量都处于同一个进程里,它们都使用该JVM进程的内存区。
调用java命令运行某个java程序时,该命令将会启动一个java虚拟机进程,不管该java程序有多么复杂,启动了多少个线程,都处于该java虚拟机进程里。
类的加载
类加载:将类的class文件读入内存,并创建一个java.lang.Class对象。
类加载器:完成类加载,由JVM提供。
系统类加载器
集成ClassLoader基类创建自己的类加载器
来源
-
从本地系统中直接加载
-
通过网络下载.class文件
-
从zip,jar等归档文件中加载.class文件
-
从专有数据库中提取.class文件
-
将Java源文件动态编译为.class文件
类的连接
类的初始化
类初始化的时机
2.类加载器
载入JVM类的标识
类名、包名、jvm实例名
层次结构
机制
全盘负责
父类委托
缓存机制
创建并使用
关键方法
loadClass(String name,boolean resolve)
该方法为classLoader的入口点,根据指定名称来加载类。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
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;
}
}
findClass(String name)
根据指定名称来查找类:
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
defineClass
defineClass()方法管理JVM许多复杂的实现,它复杂将字节码分析成运行时数据结构,并校验有效性。
@Deprecated
protected final Class<?> defineClass(byte[] b, int off, int len)
throws ClassFormatError
{
return defineClass(null, b, off, len, null);
}
自定义类加载器
URLClassLoader类
系统类加载器和扩展类加载器的父类
是ClassLoader的一个实现类
URLClassLoader(URL[] urls)
使用默认的父类加载器创建一个ClassLoader对象,该对象将从urls所指定的系列路径来查询并加载类。
public URLClassLoader(URL[] urls) {
super();
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = AccessController.getContext();
ucp = new URLClassPath(urls, acc);
}
URLClassLoader(URL[] urls,ClassLoader parent)
使用指定的父类加载器创建一个ClassLoader对象,其他功能与前一个构造器相同。
public URLClassLoader(URL[] urls, ClassLoader parent) {
super(parent);
// this is to make the stack depth consistent with 1.1
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.acc = AccessController.getContext();
ucp = new URLClassPath(urls, acc);
}