Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use ClassLoader in Java

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "how to use ClassLoader in Java". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let the editor take you to learn how to use ClassLoader in Java.

I. Preface

A complete Java application, when the program is running, will call an entry function of the program to call the relevant functions of the system, and these functions are encapsulated in different class files, so it is often necessary to call methods in another class file from this class file. If another file does not exist, a system exception will be thrown. When the program starts, it will not load all the class files used by the program at once, but according to the needs of the program, dynamically load a class file into memory through Java's class loading mechanism (ClassLoader), so that only after the class file is loaded into memory can it be referenced by other class. So ClassLoader is used to dynamically load class files into memory.

The virtual machine on the Android platform runs Dex bytecode, a product of optimization of class files. The traditional Class file is a Java source file that generates a .class file, while Android merges and optimizes all Class files. Then generate a final class.dex, the purpose is to keep only one copy of the repetition of different class files, if our Android application does not separate dex processing, the apk of the last application will only have a dex file.

2. ClassLoader in java

BootstrapClassLoader

Responsible for loading core classes of the JVM runtime, such as JAVA_HOME/lib/rt.jar, etc.

ExtensionClassLoader

Responsible for loading JVM extension classes, such as the jar package under JAVA_HOME/lib/ext

AppClassLoader

Responsible for loading jar packages and directories in classpath

3. ClassLoader in Android

BootClassLoader

In charge of Android system startup, BootClassLoader is used to preload common classes, which, unlike Bootstrap ClassLoader in Java, is not implemented by C _ Java + code, but by Java. BootClassLoader is an inner class of ClassLoader.

PathClassLoader

Responsible for loading the installed Apk, that is, the apk file under / data/app/package. You can also load the nativeLibrary under / vendor/lib, / system/lib

DexClassLoader

Responsible for loading can load an uninstalled apk file.

IV. Parental appointment mechanism

Every ClassLoader has a parent object, which represents the parent class loader. When loading a class, it will first use the parent class loader to load. If it is not found in the parent class loader, it will load itself. If the parent is empty, then use the system class loader to load. Through this mechanism, we can ensure that the system classes are loaded by the system class loader. The following is a concrete implementation of ClassLoader's loadClass method.

Protected Class loadClass (String name, boolean resolve) throws ClassNotFoundException {/ / First, check if the class has already been loaded Class c = findLoadedClass (name) If (c = = null) {try {if (parent! = null) {/ / load c = parent.loadClass (name, false) from the parent loader first;} else {c = findBootstrapClassOrNull (name) }} catch (ClassNotFoundException e) {/ / ClassNotFoundException thrown if class not found / / from the non-null parent class loader} if (c = = null) {/ / not found, then load c = findClass (name) yourself }} return c;} V. Source code analysis

1. Now let's take a look at BaseDexClassLoader inheriting from ClassLoader

Public class BaseDexClassLoader extends ClassLoader {. / / to store the dexList private final DexPathList pathList; / * * @ param dexPath that needs to be loaded, the path where the dex file needs to be loaded is * @ param optimizedDirectory Android. The path where the dex file is optimized is the storage path of the ODEX file, which must be an internal storage path. * @ param librarySearchPath the path to the c and C++ libraries used by the target class * @ param parent the parent loader of the loader, which is generally the loader of the current execution class * / public BaseDexClassLoader (String dexPath, File optimizedDirectory, String librarySearchPath, ClassLoader parent) {this (dexPath, optimizedDirectory, librarySearchPath, parent, false) } / * * @ param dexPath * @ param optimizedDirectory * @ param librarySearchPath * @ param parent * @ param isTrusted is related to whether hidden API * / public BaseDexClassLoader (String dexPath, File optimizedDirectory, String librarySearchPath, ClassLoader parent, boolean isTrusted) {super (parent) can be called; this.pathList = new DexPathList (this, dexPath, librarySearchPath, null, isTrusted) .} / * * @ param dexFiles byte cache array dex file * @ param parent the loader's parent * / public BaseDexClassLoader (ByteBuffer [] dexFiles, ClassLoader parent) {/ / TODO We should support giving this a library search path maybe. Super (parent); this.pathList = new DexPathList (this, dexFiles);} / * * find the corresponding class through the complete class name * @ param name pass in a complete class name * @ return * @ throws ClassNotFoundException * / @ Override protected Class findClass (String name) throws ClassNotFoundException {List suppressedExceptions = new ArrayList () / 1 find the class Class c = pathList.findClass (name, suppressedExceptions) corresponding to name in pathList; / / if no such class is found, throw an exception if (c = = null) {ClassNotFoundException cnfe = new ClassNotFoundException ("Didn't find class"+ name +"on path:" + pathList) For (Throwable t: suppressedExceptions) {cnfe.addSuppressed (t);} throw cnfe;} return c;}}

PathClassLoader and DexClassLoader: inherited from BaseDexClassLoader

Public class PathClassLoader extends BaseDexClassLoader {/ * * @ param dexPath dex file path collection * @ param parent parent loader * / public PathClassLoader (String dexPath, ClassLoader parent) {/ / call the parent BaseDexClassLoader four-parameter constructor super (dexPath, null, null, parent) } / * * @ param dexPath dex file path collection * @ param librarySearchPath contains the path collection of the C _ Candle library, and multiple paths are separated by a file separator The parent class BaseDexClassLoader four-parameter constructor super (dexPath, null, librarySearchPath, parent) can be called for null * @ param parent parent loader * / public PathClassLoader (String dexPath, String librarySearchPath, ClassLoader parent) {/ / }} public class DexClassLoader extends BaseDexClassLoader {/ * * @ param dexPath dex file path collection. Multiple paths are separated by a file separator. The default file separator is ":" * @ param optimizedDirectory decompressed dex file storage path. This path must be an internal storage path. In general, the private path of the current application * @ param librarySearchPath contains the path collection of the C _ blank + library, and multiple paths are separated by a file separator. You can call the parent class BaseDexClassLoader four-parameter constructor method for null * @ param parent parent loader * / public DexClassLoader (String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {/ /. If the librarySearchPath parameter is deprecated above API26, use this method super (dexPath, null, librarySearchPath, parent) / / API26 and the following use this method / / super (dexPath, new File (optimizedDirectory), librarySearchPath, parent);}}

Let's see how to find the findClass of a pathList.

/ * package*/ final class DexPathList {private static final String DEX_SUFFIX = ".dex"; private static final String zipSeparator = "! /"; private final ClassLoader definingContext; / / dex/resource array private Element for dex [] dexElements; / / list for local library files private final List nativeLibraryDirectories; / / list private final List systemNativeLibraryDirectories for system local library files / / stores the list private IOException [] dexElementsSuppressedExceptions; DexPathList (ClassLoader definingContext, String dexPath, String librarySearchPath, File optimizedDirectory, boolean isTrusted) that throws an exception when the dexElement list is created. This.definingContext = definingContext; / / BaseDexClassLoader constructor will pass its own ArrayList suppressedExceptions = new ArrayList (); / / convert it to the dexElements list this.dexElements = makeDexElements (splitDexPath (dexPath), optimizedDirectory, suppressedExceptions, definingContext, isTrusted) using delimiters through the dexPath path .} / / generate an array of directory/zip path elements for the local library search path private static Element [] makeDexElements (List files, File optimizedDirectory, List suppressedExceptions, ClassLoader loader, boolean isTrusted) {Element [] elements = new Element [files.size ()]; int elementsPos = 0 For (File file: files) {if (file.isDirectory ()) {/ / if it is a folder, add it directly to elements elements [elementsPos++] = new Element (file);} else if (file.isFile ()) {/ / if it is a file String name = file.getName (); DexFile dex = null / / whether it is a .dex file if (name.endsWith (DEX_SUFFIX)) {/ / Raw dex file (not inside a zip/jar). Try {/ / if it is a dex file, load the file dex = loadDexFile (file, optimizedDirectory, loader, elements); if (dex! = null) {/ / save the dex file. Note that the bottom null elements [elementsPos++] = new Element (dex, null) passed in the second parameter }} catch (IOException suppressed) {System.logE ("Unable to load dex file:" + file, suppressed); suppressedExceptions.add (suppressed);}} else {/ / if it is not a directory and does not end with .dex, then it may be jar. Load this file dex = loadDexFile (file, optimizedDirectory, loader, elements); if (dex = = null) {elements [elementsPos++] = new Element (file) } else {/ / saves the dex file and the current file, in which case it may be jar. For more information, please see the constructor elements [elementsPos++] = new Element (dex, file). } if (dex! = null & & isTrusted) {/ / if the dex object is not empty and the trust status is allowed dex.setTrusted (); / / set this dex object to trusted, it can access the platform's hidden api} else {System.logW ("ClassLoader referenced unknown path:" + file) }} if (elementsPos! = elements.length) {elements = Arrays.copyOf (elements, elementsPos);} return elements;} public Class findClass (String name, List suppressed) {/ / traverse dex list for (Element element: dexElements) {/ / 2 Class clazz = element.findClass (name, definingContext, suppressed) / / if we find the name class we need, directly return the current clazz if (clazz! = null) {return clazz;}} if (dexElementsSuppressedExceptions! = null) {suppressed.addAll (Arrays.asList (dexElementsSuppressedExceptions));} return null;}}

Looking at note 2, an Element array is generated through the makeDexElements method, followed by a call to the findClass method of the Element class in DexPathList by the findClass method in the current class.

Static class Element {private final File path; private final DexFile dexFile; private ClassPathURLStreamHandler urlHandler; private boolean initialized;...... Public Class findClass (String name, ClassLoader definingContext,List suppressed) {/ / 3 looks for the name class through the loadClassBinaryName method, finds it and returns it, otherwise it returns null return dexFile! = null? DexFile.loadClassBinaryName (name, definingContext, suppressed): null;}}

Note 3 through the analysis of the method of loadClassBinaryName finally calling native layer defineClassNative, we can see that the final loading operation of Class bytecode is completed through the underlying native method.

At this point, I believe you have a deeper understanding of "how to use ClassLoader in Java". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report