java 加载class_Java高级---类加载ClassLoader

任何一个java程序都是有一个或多个class文件组成的,在程序运行时,需要将class文件加载到JVM虚拟机中才可以用,负责加载这些class文件的就是java的类加载机制。

简单来说:就是加载class文件,提供给程序运行时使用。

知识点

1)基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节码,然后从这些字节码代码中定义出一个java类的实例。

2)工作原理则是通过双亲委托机制来实现的,这也可以避免重复加载,保证类的唯一性,且java类随着他的类加载器一起具备了一种带有优先级的层次关系。

​ 如何保证类的唯一性呢?

JVM在判断两个class是否相同时,不仅仅要判断两个类名是否相同,还要判断负责加载这两个类的加载器是否一样,也就是说同一个类加载器加载相同名称的类,虚拟机才会认为加载的是同一个类,否则的话认为他们是不同的类。

ClassLoader是一个抽象类,他在android中的具体实现类有:

**1. BootClassLoader:** 用于加载android Framework层的class文件

**2. PathClassLoader:** 用于加载android 应用程序中的类加载器,可以是指定的dex,jar, zip , apk中的class.dex

**3. DexClassLoader:** 用于加载指定的dex ,jar ,zip ,apk中的classes.dex

68fa6bfeaf67

类加载器类图

了解上面的一些基础概念理论的东西后,我们用一张流程图来分析一下类加载器的工作原理:

68fa6bfeaf67

类加载的工作原理流程图

知识点:

类加载的双亲委托机制

​ 类加载器在尝试自己去查找某一个类的字节码时,会先就这个任务交给他的父类加载器去尝试加载这个类,而父类加载器也先交给父类的父类加载器去执行,依次递归查找。如果父类找到了则直接返回,如果父类没有找到则再由类加载器自己查找,这种查找的方式就是双亲委托机制。

剖析源码

​ 解析来我们来从源码角度一步一步潜入类加载器中学习一下,其他类加载器的几个类都比较简单,相对复杂的是在ClassLoader.java中。废话不多说,直接开撸。。。。。。。

BaseDexClassLoader.java

public class BaseDexClassLoader extends ClassLoader {

32

33 /**

34 * Hook for customizing how dex files loads are reported.

35 *

36 * This enables the framework to monitor the use of dex files. The

37 * goal is to simplify the mechanism for optimizing foreign dex files and

38 * enable further optimizations of secondary dex files.

39 *

40 * The reporting happens only when new instances of BaseDexClassLoader

41 * are constructed and will be active only after this field is set with

42 * {@link BaseDexClassLoader#setReporter}.

43 */

44 /* @NonNull */ private static volatile Reporter reporter = null;

45

46 private final DexPathList pathList;

47

48 /**

49 * Constructs an instance.

50 * Note that all the *.jar and *.apk files from {@code dexPath} might be

51 * first extracted in-memory before the code is loaded. This can be avoided

52 * by passing raw dex files (*.dex) in the {@code dexPath}.

53 *

54 * @param dexPath the list of jar/apk files containing classes and

55 * resources, delimited by {@code File.pathSeparator}, which

56 * defaults to {@code ":"} on Android.

57 * @param optimizedDirectory this parameter is deprecated and has no effect since API level 26.

58 * @param librarySearchPath the list of directories containing native

59 * libraries, delimited by {@code File.pathSeparator}; may be

60 * {@code null}

61 * @param parent the parent class loader

62 */

63 public BaseDexClassLoader(String dexPath, File optimizedDirectory,

64 String librarySearchPath, ClassLoader parent) {

65 this(dexPath, optimizedDirectory, librarySearchPath, parent, false);

66 }

67

68 /**

69 * @hide

70 */

71 public BaseDexClassLoader(String dexPath, File optimizedDirectory,

72 String librarySearchPath, ClassLoader parent, boolean isTrusted) {

73 super(parent);

//存放dex的路径

74 this.pathList = new DexPathList(this, dexPath, librarySearchPath, null, isTrusted);

75

76 if (reporter != null) {

77 reportClassLoaderChain();

78 }

79 }

80

81

113 /**

114 * Constructs an instance.

115 *

116 * dexFile must be an in-memory representation of a full dexFile.

117 *

118 * @param dexFiles the array of in-memory dex files containing classes.

119 * @param parent the parent class loader

120 *

121 * @hide

122 */

123 public BaseDexClassLoader(ByteBuffer[] dexFiles, ClassLoader parent) {

124 // TODO We should support giving this a library search path maybe.

125 super(parent);

126 this.pathList = new DexPathList(this, dexFiles);

127 }

128

129 @Override

130 protected Class> findClass(String name) throws ClassNotFoundException {

131 List suppressedExceptions = new ArrayList();

132 Class c = pathList.findClass(name, suppressedExceptions);

133 if (c == null) {

134 ClassNotFoundException cnfe = new ClassNotFoundException(

135 "Didn't find class \"" + name + "\" on path: " + pathList);

136 for (Throwable t : suppressedExceptions) {

137 cnfe.addSuppressed(t);

138 }

139 throw cnfe;

140 }

141 return c;

142 }

281}

2. PathClassLoader.java

public class PathClassLoader extends BaseDexClassLoader {

26 /**

27 * Creates a {@code PathClassLoader} that operates on a given list of files

28 * and directories. This method is equivalent to calling

29 * {@link #PathClassLoader(String, String, ClassLoader)} with a

30 * {@code null} value for the second argument (see description there).

31 *

32 * @param dexPath the list of jar/apk files containing classes and

33 * resources, delimited by {@code File.pathSeparator}, which

34 * defaults to {@code ":"} on Android

35 * @param parent the parent class loader

36 */

37 public PathClassLoader(String dexPath, ClassLoader parent) {

38 super(dexPath, null, null, parent);

39 }

40

41 /**

42 * Creates a {@code PathClassLoader} that operates on two given

43 * lists of files and directories. The entries of the first list

44 * should be one of the following:

45 *

46 *

47 *

JAR/ZIP/APK files, possibly containing a "classes.dex" file as

48 * well as arbitrary resources.

49 *

Raw ".dex" files (not inside a zip file).

50 *

51 *

52 * The entries of the second list should be directories containing

53 * native library files.

54 *

55 * @param dexPath the list of jar/apk files containing classes and

56 * resources, delimited by {@code File.pathSeparator}, which

57 * defaults to {@code ":"} on Android

58 * @param librarySearchPath the list of directories containing native

59 * libraries, delimited by {@code File.pathSeparator}; may be

60 * {@code null}

61 * @param parent the parent class loader

62 */

63 public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {

64 super(dexPath, null, librarySearchPath, parent);

65 }

66}

DexClassLoader.java

public class DexClassLoader extends BaseDexClassLoader {

36 /**

37 * Creates a {@code DexClassLoader} that finds interpreted and native

38 * code. Interpreted classes are found in a set of DEX files contained

39 * in Jar or APK files.

40 *

41 *

The path lists are separated using the character specified by the

42 * {@code path.separator} system property, which defaults to {@code :}.

43 *

44 * @param dexPath the list of jar/apk files containing classes and

45 * resources, delimited by {@code File.pathSeparator}, which

46 * defaults to {@code ":"} on Android

47 * @param optimizedDirectory this parameter is deprecated and has no effect since API level 26.

48 * @param librarySearchPath the list of directories containing native

49 * libraries, delimited by {@code File.pathSeparator}; may be

50 * {@code null}

51 * @param parent the parent class loader

52 */

53 public DexClassLoader(String dexPath, String optimizedDirectory,

54 String librarySearchPath, ClassLoader parent) {

55 super(dexPath, null, librarySearchPath, parent);

56 }

57}

ClassLoader.java

protected Class> loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

// First, check if the class has already been loaded

//从JVM缓存中已经加载的Class中进行查找,已经加载过,则直接返回

//findLoadedClass返回会先判断当前的类加载器是否是BootClassLoader?如果不是,那么就将当前的加载器传递给VMClassLoader : 如果是,则给VMClassLoader传递空值进去

// 最后再通过native方法在缓存中查找

Class> c = findLoadedClass(name);

if (c == null) {

//父类加载器加载

try {

if (parent != null) {

//双亲委托,递归交给父类加载器进行加载,

c = parent.loadClass(name, false);

} else {

//此方法返回null

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.

//findClass 系统提供的是会直接抛出异常 throw new ClassNotFoundException(name)

//我们可以在自己的类加载器中重写findClass方法,来做到我们自己去查找加载类的功能

c = findClass(name);

}

}

return c;

}

以上就是笔者想要和大家分享的关于类加载器的一些内容,那么我们实际工作中该如何使用呢?持续完善中。。。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值