本文共 3322 字,大约阅读时间需要 11 分钟。
jvm赋能java跨平台的能力,而类加载机制是深入理解java的必要条件。 我是李福春,我在准备面试,今天的问题是: java的类加载机制是怎样的?什么是双亲委派原则? 答:java的类加载过程分为 加载,链接,初始化。 加载:即从数据源(jar,class,网络)加载class文件到jvm,映射为class对象,如果不是classFile结构,抛出ClassFormatError; 链接:把第一步得到的class对象转换到jvm环境,进行验证(字节信息是否符合jvm规范,否则抛出VerifyError),准备(为静态变量分配内存空间),解析(常量池中的符号引用替换为直接引用); 初始化:即为静态变量和静态代码块赋值。 java的类加载器部分的加载器分4类,见上图。 BootStrapClassLoader:加载jre/lib下的jdk的jar包,具有超级权限,是最顶级的类加载器; ExtensionClassLoader:加载jre/lib/ext下的jar包,加载jdk的扩展程序包; ApplicationClassLoader:加载当前应用classpath下的jar包或者class文件; 自定义ClassLoader:用户自定义的类加载器,一般是为了进行进程隔离,或者自己操纵字节码; 双亲委派机制:即为了避免类信息被重复加载和程序的安全性,父加载器优先子加载器加载类型到jvm,子加载器无法加载父加载器已经加载到jvm中的类型信息。 下面做一下扩展:针对面试官可能会追问的细节。java -Xbootclasspath/a: your_App
java -Xbootclasspath/p: your_App
指定扩展加载器的目录:```javajava -Djava.ext.dirs=your_ext_dir HelloWorld指定系统加载器的实现类:
java -Djava.system.class.loader=com.yourcorp.YourClassLoader HelloWorld打印出类加载器: ```java package org.example.mianshi.classloader;
import java.util.Collection;
/**
public class PrintClassLoaderApp {
public static void main(String[] args) { System.out.println("PrintClassLoaderApp 的类加载器是:"+PrintClassLoaderApp.class.getClassLoader()); System.out.println("parent 的类加载器是:"+ PrintClassLoaderApp.class.getClassLoader().getParent()); System.out.println("parent.parent 的类加载器是:"+ PrintClassLoaderApp.class.getClassLoader().getParent().getParent()); System.out.println("Collection 的类加载器是:"+ Collection.class.getClassLoader());}
}
输出结果:我使用的java10,PlatformClassLoader替代了ExtensionClassLoader;```javaPrintClassLoaderApp 的类加载器是:jdk.internal.loader.ClassLoaders$AppClassLoader@4459eb14parent 的类加载器是:jdk.internal.loader.ClassLoaders$PlatformClassLoader@2ac1fdc4parent.parent 的类加载器是:nullCollection 的类加载器是:null
自定义类加载器一般用来进行进程内隔离,或者需要自己操纵字节码的场景。
过程如下:1,通过名称找到二进制代码,即class文件;2,使用class文件创建对应的class对象; 示例代码如下:package org.example.mianshi.classloader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import java.io.InputStream;/** * 作者: carter * 创建日期: 2020/3/31 14:24 * 描述: 自定义类加载器 */public class CustomerClassLoaderApp extends ClassLoader { @Override protected Class findClass(String name) throws ClassNotFoundException { byte[] bytes = loadClassFromFile(name); return defineClass(name, bytes, 0, bytes.length); } private byte[] loadClassFromFile(String name) { InputStream inputStream = getClass().getClassLoader() .getResourceAsStream(name.replace(".", File.separator) + ".class"); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int nextValue = 0; try { while ((nextValue = inputStream.read()) != -1) { byteArrayOutputStream.write(nextValue); } } catch (IOException e) { e.printStackTrace(); } byte[] buffer = byteArrayOutputStream.toByteArray(); return buffer; }}
原创不易,转载请注明出处,让我们互通有无,共同进步,欢迎多沟通交流