Java中的ClassLoader具体解说

java中的.java文件经过编译今后,号码大全就会生成类文件.class文件关键词挖掘工具。class文件是以二进制字节码寄存在硬盘中的。当咱们需求运用或加载Java文件到JVM中的时分,会从硬盘中读取字节码的class文件,然后经过类加载器将class文件加载到JVM中。也即是说,一切的Java文件都是经过类加载器加载到JVM中的。当然类加载器也是一个Java文件。那么第一个类加载器又是怎么加载到JVM中的呢?在发动JVM的时分,会调运一个本地办法findBootStrapClass办法加载最初始的那个ClassLoader,private native Class findBootstrapClass(String name),这个本地办法运用C++编写的。

1.体系已有3品种加载器

1.1 BooststrapClassLoader(boot) 加载rt.jar下面的类(此加载器采用C++编写,通常开发中是看不到的)

1.2 ExtClassLoader  加载ExtClassLoader下面的类(ext文件夹下面的jar)

1.3 AppClassLoader  加载classpaht下面的类

咱们写的类简直都是经过AppClassLoader这个加载器加载到JVM中的。

2.类加载器的加载机制(双亲托付机制)

每一个类加载器都有一个对应的parentClassLoader。

2.1    体系类加载器的父子关系

自界说类加载器的爸爸是AppClassLoader

AppClassLoader的爸爸是ExtClassLoader

ExtClassLoader的爸爸是BooststrapClassLoader

Java代码  保藏代码

public class TestClassLoader {

public static void main(String[] args) {

// 当时目标的类加载器

ClassLoader loader = new TestClassLoader().getClass().getClassLoader();

// 从当时目标的类加载器想上找他的各个祖先

while (loader != null) {

System.out.println(loader.getClass().getName());

loader = loader.getParent();

}

// 晓得找到最终的祖先是null

System.out.println(loader);

}

}

输出:

sun.misc.Launcher$AppClassLoader

sun.misc.Launcher$ExtClassLoader

null

2.2    类加载器加载的次序

类加载器是从根向下加载的

也即是boot-》ExiClassLoader -》AppClassLoader

当一个类需求被加载的时分,首要是由AppClassLoader加载器将其传递给其爸爸ExtClassLoader,然后ExtClassLoader再将其传递给他的爸爸boot。

当boot发现他的加载规模内有对应的class,就加载到JVM中,否则交给儿子ExtClassLoader处置。

ExtClassLoader再在他的加载规模类找有没有对应的class,有就加载到JVM中,没有就交给AppClassLoader处置。

AppClassLoader再在classpath途径下找对应的class,找到就加载,没有就报反常。

缘由:这样能够确保JVM中某一个className对应的是同一个class,由于都是从根向下加载的。

避免重复加载,当爸爸现已加载了该类的时分,就没有必要子ClassLoader再加载一次。

要是从下向上加载,能够致使某一个className在JVM中对应好几个class。能够咱们会界说自个的类加载器和自个的加载规模。

当自个界说的类加载在他们各自的规模都发现需求加载的类,那么他们能够都会加载,致使JVM中一个className对应好几个不一样的class

2.3    比方咱们自个界说一个类加载器去加载java.lang.String这个类,那么咱们是不能到达咱们目的的。

由于加载机制是从上到下加载,当传递到上面的boot的时分,现已被加载到JVM中,轮不到咱们自界说的类加载器去加载它。

但是,咱们肯定是能够自个界说一个类加载器去加载咱们指定的类的。

3.怎么自界说一个类加载

首要,咱们需求承继ClassLoadar

然后,咱们不能破坏本来的类加载机制(双亲托付机制),所以咱们不能掩盖loadClass办法,咱们需求掩盖findclass办法。

最终,在findClass办法中写入咱们的类加载器的代码。

查看源码解说:

Java代码  保藏代码

protected Class loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

synchronized (getClassLoadingLock(name)) {

// 首要查看name对应的Class是不是现已被加载

Class c = findLoadedClass(name);

//假如没有被加载

if (c == null) {

long t0 = System.nanoTime();

//测验让parentClassLoader去加载

try {

if (parent != null) {

//当parent不为null的时分,让parent去loadClass

c = parent.loadClass(name, false);

} else {

//当parent为null的时分,就调运本地办法

c = findBootstrapClassOrNull(name);

}

} catch (ClassNotFoundException e) {

}

//当parentClassLoader没有加载的时分

if (c == null) {

long t1 = System.nanoTime();

//调运findClass办法去加载

c = findClass(name);

}

}

-        indexRead arguments from command-line "http://www.shoudashou.com"

-        indexRead arguments from command-line "http://www.4lunwen.cn"

-        indexRead arguments from command-line "http://www.zx1234.cn"

-        indexRead arguments from command-line "http://www.penbar.cn"

-        indexRead arguments from command-line "http://www.whathappy.cn"

-        indexRead arguments from command-line "http://www.lunjin.net"

-        indexRead arguments from command-line "http://www.ssstyle.cn"

-        indexRead arguments from command-line "http://www.91fish.cn"

-        indexRead arguments from command-line "http://www.fanselang.com"

if (resolve) {

resolveClass(c);

}

return c;

}

}

4.举例

目标:自界说一个类加载器加咱们指定途径下,经过我么加密的class。

进程:找到指定途径下的class文件,解密,加载到JVM中。

4.1先界说一个需求被加密编译的类,一起运用它进行测验

Java代码  保藏代码

public class MyClass extends Date {

@Override

public String toString() {

return "hello world";

}

}

4.2加密本来的class文件

Java代码  保藏代码

public static void main(String[] args) throws Exception {

String inputSrc = args[0];//本来的class文件的途径和文件名

String outputSrc = args[1];//加密今后寄存的文件途径和文件名

FileInputStream fis = new FileInputStream(inputSrc);

FileOutputStream fos = new FileOutputStream(outputSrc);

//调用加密算法

cypher(fis, fos);

fis.close();

fos.close();

}

/**

* 加密解密函数办法

*

* @param is

* @param os

* @throws IOException

*/

private static void cypher(InputStream is, OutputStream os) throws IOException {

int b = -1;

while ((b = is.read()) != -1) {

// 将0成为1,将1成为0

os.write(b ^ 0xff);

}

}

4.3编写咱们自个的类加载器

Java代码  保藏代码

public class MyClassLoader extends ClassLoader {

//要加载的类的途径

private String classSrc;

public MyClassLoader() {

}

public MyClassLoader(String classSrc) {

this.classSrc = classSrc;

}

@Override

protected Class findClass(String name) throws ClassNotFoundException {

//先找到自个的加密的class文件的方位

String classFielName = classSrc + "\\" + name + ".class";

try {

FileInputStream fis = new FileInputStream(classFielName);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

//调运解密算法

cypher(fis, baos);

fis.close();

byte[] bytes = baos.toByteArray();

//将读出来的二进制转换为Class字节码

return defineClass(null, bytes, 0, bytes.length);

} catch (Exception e) {

e.printStackTrace();

}

return super.findClass(name);

}

}

4.4运用咱们自个的类加载加载咱们加密的类到JVM中

Java代码  保藏代码

//首要运用自个的类加载器去加载咱们加密的class文件

//留意,这个当地的加载类的途径下的class应该是咱们加密今后文件的方位

Class clazz = new MyClassLoader("E:/AllWorkspace/workspace1/classLoaderTest/bin/com/gusi/test").loadClass("MyClass");

//经过反射,测验咱们的classLoader

Date date = (Date) clazz.newInstance();

System.out.println(date.toString());

Java中的ClassLoader具体解说

时间: 2024-12-09 18:50:30

Java中的ClassLoader具体解说的相关文章

Java中的ClassLoader详细解释

java中的.java文件经过编译以后,就会生成类文件.class文件.class文件是以二进制字节码存放在硬盘中的.当我们需要使用或加载Java文件到JVM中的时候,会从硬盘中读取字节码的class文件,然后通过类加载器将class文件加载到JVM中.也就是说,所有的Java文件都是通过类加载器加载到JVM中的.当然类加载器也是一个Java文件.那么第一个类加载器又是如何加载到JVM中的呢?在启动JVM的时候,会调运一个本地方法findBootStrapClass方法加载最初始的那个Class

一看你就懂,超详细 java 中的 ClassLoader 详解

ClassLoader翻译过来就是类加载器,普通的java开发者其实用到的不多,但对于某些框架开发者来说却非常常见.理解ClassLoader的加载机制,也有利于我们编写出更高效的代码.ClassLoader的具体作用就是将class文件加载到jvm虚拟机中去,程序就可以正确运行了.但是,jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载.想想也是的,一次性加载那么多jar包那么多class,那内存不崩溃.本文的目的也是学习ClassLoader这种加载机制. 备注:

一看你就懂,超详细java中的ClassLoader详解

本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 ClassLoader翻译过来就是类加载器,普通的java开发者其实用到的不多,但对于某些框架开发者来说却非常常见.理解ClassLoader的加载机制,也有利于我们编写出更高效的代码.ClassLoader的具体作用就是将class文件加载到jvm虚拟机中去,程序就可以正确运行了.但是,jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载.想想也是的,一次性加载那么多jar包那么多class,那内存不

Java中对于ClassLoader类加载器 嵌套了深度技术的价值

关于Java技术是一种不断兴起的编程语言,对于ClassLoader 是 Java 届最为神秘的技术之一,无数人被它伤透了脑筋,摸不清门道究竟在哪里.本文我带你彻底吃透 ClassLoader,让你甚至Java类加载器的神奇之处  1.ClassLoader 做什么的? 顾名思义,它是用来加载 Class 的.它负责将 Class 的字节码形式转换成内存形式的 Class 对象.字节码可以来自于磁盘文件 *.class,也可以是 jar 包里的 *.class,也可以来自远程服务器提供的字节流,

JAVA学习之ClassLoader

JAVA学习之ClassLoader 前言 最近被 一句话所触动--种一棵树最好的时间是十年前,其次是现在.所以决定要开始记录自己的学习之路. 什么是类加载? 我们都知道,每个.java文件可以经过javac指令编译成.class文件,里面包含着java虚拟机的机器指令.当我们需要使用一个java类时,虚拟机会加载它的.class文件,创建对应的java对象.将.class调入虚拟机的过程,称之为加载. loading :加载.通过类的完全限定名找到.class字节码文件,同时创建一个对象. v

[Java类加载器]Java中classLoader浅析.

本文为在公司内部TD上写的一篇小文, 主要讲解java中classLoader基础知识, 现在拿来这里分享一下. 一.问题 请在Eclipse中新建如下类,并运行它: 1 package java.lang; 2 3 public class Long { 4 public static void main(String[] args) { 5 System.out.println("Hi, i am here"); 6 } 7 } 你能猜到它的运行如果吗? 不错,就是如下这个样子!

对java中classloader使用的一点理解(转)

先简单介绍下java的classloader,网上资料很多,就说点关键的. Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的.系统提供的类加载器主要有下面三个: 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader. 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库.Java 虚拟

ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗

1.ClassLoader Java中类加载出现在哪个阶段,编译期和运行期? 类加载和类装载是一样的吗? :当然是运行期间啊,我自己有个理解误区,改正后如下:编译期间编译器是不去加载类的,只负责编译而已,去rt.jar拿数据干嘛,不依然是class文件,jvm是只要是class文件就能运行. 2.类加载ClassLoader,各个类加载器执行顺序是什么? :永远是自己写的加载器先去加载,记住并不是真正的加载,而是双亲委派机制,每个加载器都不真正去加载,而是去让父加载器去加载,想一下,自然界亦是如

Java - Java 中的三种 ClassLoader

1.虚拟机类加载器(称为"bootstrap class loader"),它本身没有父类加载器,它负责加载虚拟机的内置类,由于它是用C.C++写的,所以Java无法拿到其class文件,返回的都是空,因为C.C++编译后不是*.class文件 2.JDK扩展类加载器(sun.misc.Launcher$ExtClassLoader),它是虚拟机类加载器的子类,它负责加载java.x包下的类. 3.系统(应用)类加载器(sun.misc.Launcher$AppClassLoader)