面试刷题23:类加载过程和双亲委派机制?
2020-03-31 16:08:40来源:博客园 阅读 ()
面试刷题23:类加载过程和双亲委派机制?
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 # 指定新的bootclasspath,替换java.*包的内部实现 java -Xbootclasspath:
a意味着append,将指定目录添加到bootclasspath后面
java -Xbootclasspath/a:<your_dir> your_App
p意味着prepend,将指定目录添加到bootclasspath前面
java -Xbootclasspath/p:<your_dir> your_App
<br />
<br />指定扩展加载器的目录:
```java
java -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;
/**
- 作者: carter
- 创建日期: 2020/3/31 12:41
- 描述: 类加载器的层级关系
*/
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());
}
}
<br />输出结果:<br />我使用的java10,PlatformClassLoader替代了ExtensionClassLoader;
```java
PrintClassLoaderApp 的类加载器是:jdk.internal.loader.ClassLoaders$AppClassLoader@4459eb14
parent 的类加载器是:jdk.internal.loader.ClassLoaders$PlatformClassLoader@2ac1fdc4
parent.parent 的类加载器是:null
Collection 的类加载器是: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;
}
}
如何加速类加载
1,? ?AOT , 即提前把字节码编译成机器码,然后在启动的时候指定机器码的位置,
2,AppCDS ,即提前把类信息加载成为元数据,使用内存映射技术,免除类加载和解析的开销。
小结
本节回顾了jvm的类加载过程,类加载器的层次,双亲委派原则,
然后指明了自定义类加载器的使用场景和基本过程,以及给了一个简单的例子;
最后给出了两种加速类加载器速度的方法。
原创不易,转载请注明出处。
原文链接:https://www.cnblogs.com/snidget/p/12605134.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- JVM常见面试题解析 2020-06-11
- 作为一个面试官,我想问问你Redis分布式锁怎么搞? 2020-06-10
- 送你一份年薪百万的抖音Java岗内部面试题 2020-06-09
- 一口气说出 6种 延时队列的实现方案,面试稳稳的 2020-06-08
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash