都工作3年了,怎么能不懂双亲委派呢?(带你手把手断点源码)(3)

}

}
class B extends A {
public static Integer num = 20;
static {
System.out.println(“B loader…”);
}
}



> 
> Tips:**不管是用什么方法加载,类从始至终只会加载一次;**
> 
> 
> 



### 2.3 类加载器



#### 2.3.1 类加载器的种类


* **启动类加载器Bootstrap ClassLoader:** 是嵌在JVM内核中的加载器,该加载器是用C++语言写的,主要负则加载JAVA\_HOME/lib下的类库,启动类加载器无法被应用程序直接使用。
* \*\*扩展类加载器Extension ClassLoader:\*\*该加载器器是用JAVA编写,且它的父加载器是Bootstrap,是由sun.misc.Launcher$ExtClassLoader实现的,主要加载JAVA\_HOME/lib/ext目录中的类库。开发者可以这几使用扩展类加载器。
* \*\*系统类加载器App ClassLoader:\*\*系统类加载器,也称为应用程序类加载器,负责加载应用程序classpath目录下的所有jar和class文件(第三方jar)。它的父加载器为Ext ClassLoader。



> 
> Tips:这里的父加载器**并非是Java中的继承关系**,而是我们后面学习双亲委派过程中向上委派的加载器,我们将其称为父加载器;
> 
> 
> 




---


测试类:



package com.dfbz.demo01;
import com.dfbz.demo02.Demo02;
import com.sun.java.accessibility.AccessBridge;
import org.junit.Test;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo02_类加载器的种类 {
@Test
public void test1(){
// Bootstrap类加载器是获取不到的,为null
System.out.println("Bootstrap ClassLoader: "+ String.class.getClassLoader());
// jre\lib\ext\access-bridge-64.jar
System.out.println("ExtClassLoader ClassLoader: "+ AccessBridge.class.getClassLoader());
System.out.println("AppClassLoader ClassLoader: "+ Demo02.class.getClassLoader());
}
}



#### 2.3.2 双亲委派机制


从JDK1.2开始,类的加载过程采用双亲委派机制,它是一种任务委派模式。即把加载类的请求交由父加载器处理,一直到顶层的父加载器(BootstrapClassLoader);如果父加载器能加载则用父加载器加载,否则才用子加载器加载该类;


* 示例代码:



package com.dfbz.demo01;
import org.junit.Test;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo03_类加载的过程 {
@Test
public void test1() {
Class tClass = T.class;
System.out.println(tClass);
}
class T {
}
}


JVM在加载类时,会调用类加载器(ClassLoader)的loadClass方法进行加载;  
ClassLoader类加载源码:



protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 检查该类是否被加载过 Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
// 使用父加载器加载
c = parent.loadClass(name, false);
} else {

                // 如果没有父加载器则使用BootstrapClassLoader加载
                c = findBootstrapClassOrNull(name);
            }
        } catch (ClassNotFoundException e) {
            // ClassNotFoundException thrown if class not found
            // from the non-null parent class loader
        }
        if (c == null) {
            // 如果依旧没有加载,则调用自身的findClass方法进行加载
            long t1 = System.nanoTime();
            c = findClass(name);
            // this is the defining class loader; record the stats
            sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
            sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
            sun.misc.PerfCounter.getFindClasses().increment();
        }
    }
    if (resolve) {
        resolveClass(c);
    }
    return c;
}

}


findClass方法源码:



protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}


可以看到,默认情况下ClassLoader的findClass方法只是抛出了一个异常而已(这个方法是留给我们写的)




---


* 双亲委派机制流程图:


![](https://img-blog.csdnimg.cn/img_convert/75c3b847c7083542a974a4e824427040.png#id=naoEg&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)


* 1)从上图我们可以分析,当一个Demo.class这样的文件要被加载时,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。


![](https://img-blog.csdnimg.cn/img_convert/e0fc38b202b05223ad562466f6c8c18d.png#id=APiQw&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)![](https://img-blog.csdnimg.cn/img_convert/c646d1d942ce71ae42cd9862e3bd3ba3.png#id=UHdRz&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)


* 2)**如果没有加载,那么会拿到父加载器(向上委派),然后调用父加载器的loadClass方法进行加载**。AppClassLoader的父加载器为ExtClassLoader,而ExtClassLoader并没有重写loadClass方法,因此还是调用ClassLoader类的loadClass方法,相当于是一个递归的操作;


![](https://img-blog.csdnimg.cn/img_convert/904f02e976b70e567605b620229fe89b.png#id=rqi9S&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)


* 3)父类中同理也会先检查自己是否已经加载过,如果没有再往上。注意是个递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会**下沉**到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。


![](https://img-blog.csdnimg.cn/img_convert/b139d8ba019e5dd45d168e90c64ce963.png#id=HbaBm&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
BootstrapClassLoader不能加载该类,因此还是为null,然后调用本类的findClass方法;这里需要注意两点:


* 1)本类还是ExtClassLoader
* **2)ExtClassLoader是自身没有findClass方法,但ExtClassLoader继承与URLClassLoader,并且URLClassLoader提供有findClass方法;**


![](https://img-blog.csdnimg.cn/img_convert/06632098542c9b96238d183e0f84ebc2.png#id=mAuYH&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
接下来调用到URLClassLoader类中的findClass方法来加载该类:  
![](https://img-blog.csdnimg.cn/img_convert/19fbaee0a8096cd8c580a378bf13048c.png#id=THoEs&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
URLClassLoader类中的findClass方法无法加载我们传递的类,然后向上抛出了一个异常;这里需要注意:


* **1)URLClassLoader类中的findClass方法是通过ExtClassLoader调用findClass方法进去的,因此向上抛出异常后,findClass方法后面的代码将不会执行了,并且触发的异常继续往上抛给调用者(调用loadClass的对象)**
* **2)ExtClassLoader的loadClass方法是在AppClassLoader中,通过parent.loadClass()调用进去的,因此异常被抛到了这里;**


![](https://img-blog.csdnimg.cn/img_convert/22b8378f9246179037f0886ba137d67f.png#id=QBOYN&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
**异常被抛到了AppClassLoader中的loadClass方法中,接着尝试使用AppClassLoader的findClass()方法来加载类;**  
![](https://img-blog.csdnimg.cn/img_convert/8533329f5b173e62a0a035e0a810f3da.png#id=DtM4p&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
最终交给AppClassLoader完成类的加载:  
![](https://img-blog.csdnimg.cn/img_convert/e62159865616588271968f18d34f0d6c.png#id=kM9wJ&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
 


#### 2.3.3 双亲委派的好处


我们已经了解了Java中类加载的双亲委派机制,\*\*即加载类时交给父加载器加载,如果父加载器不能加载,再交给子加载器加载;\*\*这样做有何好处呢?


* 1)**避免类的重复加载**:当父类加载器已经加载了该类时,就没有必要子 ClassLoader 再加载一次。
* 2)**安全问题**:有了双亲委派机制,当有人想要替换系统级别的类或者篡改他的实现时,在双亲委派机制下,在任何的Java代码运行之前,会将所有要用到的系统类提前使用BootstrapClassLoader加载进内存(而当一个类需要被加载时必定会轮到BootstrapClassLoader来加载,只是是否能加载的问题,不能加载的必定不是系统级别的类),所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入。




---


在指定的系统包下建立指定的类(由BootstrapClassLoader、ExtClassLoader加载的系统类):  
![](https://img-blog.csdnimg.cn/img_convert/dfcdf5c62c5a8b12547161599acee723.png#id=FuuVr&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)


* Object:



package java.lang;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Object {
static {
System.out.println(“自定义的Object类被加载了…”);
}
}


* AccessBridge:



package com.sun.java.accessibility;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class AccessBridge {
static {
System.out.println(“自定义的AccessBridge类被加载了…”);
}
}


* 测试类:



package com.dfbz.demo01;
import com.sun.java.accessibility.AccessBridge;
import org.junit.Test;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo04_双亲委派的好处 {
@Test
public void test1() {
// java.lang.Object 类在JVM启动时就已经被加载过了,因此不会再被加载了
Class clazz = Object.class;
// com.sun.java.accessibility.AccessBridge 类在JVM启动时就已经被加载过了,因此不会再被加载了
Class accessBridgeClass = AccessBridge.class;
}
}



> 
> Tips:**根据双亲委派机制,我们自定义的Object、AccessBridge类不可能被加载;**
> 
> 
> 


另外,JVM的类加载器对包名的定义也有限制;不允许我们自定义系统包名  
在系统包名下创建任意一个类:  
![](https://img-blog.csdnimg.cn/img_convert/55d68f93dc7bcbce8da44bd8d775be70.png#id=Ffetl&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)



@Test
public void test2() {
// 不允许用户将类定义在受限包名下 ,Prohibited package name: java.lang
Class clazz = AA.class;
}


运行结果:  
![](https://img-blog.csdnimg.cn/img_convert/2620adbe543267f4f6f648486c4b6042.png#id=f7FwS&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
 


#### 2.3.4 URLClassLoader类加载器


在 java.net 包中,JDK提供了一个更加易用的类加载器URLClassLoader,它扩展了 ClassLoader,能够从本地或者网络上指定的位置加载类,我们可以使用该类作为自定义的类加载器使用。  
URLClassLoader的构造方法:


* `public URLClassLoader(URL[] urls)`:指定要加载的类所在的URL地址,父类加载器默认为系统类加载器
* `public URLClassLoader(URL[] urls, ClassLoader parent)`:指定要加载的类所在的URL地址,并指定父类加载器。


##### 1)加载本地磁盘上的类:


在指定目录下准备一个Java文件并把它编译成class文件:


* Show.java:



package com.dfbz.demo01;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Show {
public Show(){
System.out.println(“new Show…”);
}
}


* 编译文件:



D:\000\com\dfbz\demo01>javac Show.java
D:\000\com\dfbz\demo01>


![](https://img-blog.csdnimg.cn/img_convert/f5b4a5cb7103ff762b75f92b88c2d02c.png#id=XnIKf&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)


* 测试代码:



package com.dfbz.demo01_类加载器的功能;
import org.junit.Test;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo05_URLClassLoader {
@Test
public void test() throws Exception{
File file = new File(“D:\000”);
// file —> URI
URI uri = file.toURI();
// URI —> URL
URL url = uri.toURL();
// 根据URL构建一个类加载器
URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
System.out.println(“父类加载器:” + classLoader.getParent()); // 默认父类加载器是系统类加载器
Class clazz = classLoader.loadClass(“com.dfbz.demo01.Show”);
// 实例化这个类
clazz.newInstance();
}
}


运行结果:  
![](https://img-blog.csdnimg.cn/img_convert/f5d7226f4816790c52b6eaf633239f2d.png#id=uoGSB&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)  
 


##### 2)加载网络上的类:



@Test
public void test2() throws Exception{
// 构建一个网络地址
URL url = new URL(“http://www.baidu.com/class/”);

URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
System.out.println("父类加载器:" + classLoader.getParent());         // 默认父类加载器是系统类加载器
Class clazz = classLoader.loadClass("com.baidu.demo.Show");

// 实例化这个类
clazz.newInstance();

}



> 
> Tips:关于加载网络上的类,等我们以后学习了服务器编程再来体验!
> 
> 
> 



#### 2.3.5 自定义类加载器


我们如果需要自定义类加载器,只需要继承ClassLoader,并覆盖掉findClass方法即可。



> 
> Tips:我们自定义的类加载器的父加载器为AppClassLoader;
> 
> 
> 


* 自定义类加载器:



package com.dfbz.demo02;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
// 1. 继承 ClassLoader
// 2. 覆盖 findClass方法
public class MyClassLoader extends ClassLoader {
// 被加载类所在的目录
private String dir;
public MyClassLoader(String dir) { // 默认父类加载器就是系统类加载器 AppClassLoader
this.dir = dir;
}
public MyClassLoader(ClassLoader parent, String dir) {
super(parent);
this.dir = dir;
}
/**
*
* @param name
* @return 重写findClass方法
* @throws ClassNotFoundException
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
// 把类名转换为目录 —> D:/000/com/dfbz/demo01/Show.class
String file = dir + “/” + name.replace(“.”, “/”) + “.class”;
// 从文件中读取这个Class文件
InputStream in = new FileInputStream(file);
// 构建一个内存输出流(将读取到的Class文件写在内存中)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len ;

如何自学黑客&网络安全

黑客零基础入门学习路线&规划

初级黑客
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(一周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(一周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(一周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)
恭喜你,如果学到这里,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web 渗透、安全服务、安全分析等岗位;如果等保模块学的好,还可以从事等保工程师。薪资区间6k-15k

到此为止,大概1个月的时间。你已经成为了一名“脚本小子”。那么你还想往下探索吗?

如果你想要入坑黑客&网络安全,笔者给大家准备了一份:282G全网最全的网络安全资料包评论区留言即可领取!

7、脚本编程(初级/中级/高级)
在网络安全领域。是否具备编程能力是“脚本小子”和真正黑客的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力.

如果你零基础入门,笔者建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习;搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP, IDE强烈推荐Sublime;·Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,不要看完;·用Python编写漏洞的exp,然后写一个简单的网络爬虫;·PHP基本语法学习并书写一个简单的博客系统;熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选);·了解Bootstrap的布局或者CSS。

8、超级黑客
这部分内容对零基础的同学来说还比较遥远,就不展开细说了,附上学习路线。
img

网络安全工程师企业级学习路线

img
如图片过大被平台压缩导致看不清的话,评论区点赞和评论区留言获取吧。我都会回复的

视频配套资料&国内外网安书籍、文档&工具

当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

img
一些笔者自己买的、其他平台白嫖不到的视频教程。
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值