当前位置: 首页 > news >正文

aspcms网站打不开最新中高风险地区名单

aspcms网站打不开,最新中高风险地区名单,青岛官网seo方法,dede复制网站模板目录 什么是类加载器 类加载器的分类 Bootstrap启动类加载器 通过启动类加载器加载用户jar包 Extension扩展类加载器和Application应用程序类加载器 通过扩展类加载器加载用户jar包 双亲委派机制 打破双亲委派机制 自定义类加载器 线程上下文类加载器 Osgi框架的类加…

目录

什么是类加载器

类加载器的分类

Bootstrap启动类加载器

通过启动类加载器加载用户jar包

Extension扩展类加载器和Application应用程序类加载器

通过扩展类加载器加载用户jar包

双亲委派机制

打破双亲委派机制

自定义类加载器

线程上下文类加载器

Osgi框架的类加载器

总结

JDK9之后的类加载器


什么是类加载器

类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术,类加载器只参与加载过程中的字节码获取并加载到内存这一部分。

类加载器会通过二进制流的方式获取到字节码文件的内容,接下来将获取到的数据交给Java虚拟机,虚拟机会在方法区和堆上生成对应的对象保存字节码信息。

类加载器的分类

类加载器分为两类,一类是Java代码中实现的,一类是Java虚拟机底层源码实现的。

1. JDK中默认提供或者自定义:JDK中默认提供了多种处理不同渠道的类加载器,程序员也可以自己根据需求定制,使用Java语言。所有Java中实现的类加载器都需要继承ClassLoader这个抽象类。
2. 虚拟机底层实现:源代码位于Java虚拟机的源码中,实现语言与虚拟机底层语言一致,比如Hotspot使用C++。主要目的是保证Java程序运行中基础类被正确地加载,比如java.lang.String,Java虚拟机需要确保其可靠性。

类加载器的设计JDK8和8之后的版本差别较大,首先来看JDK8及之前的版本,这些版本中默认的类加载器有如下几种:


Bootstrap启动类加载器

1. 启动类加载器(Bootstrap ClassLoader)是由Hotspot虚拟机提供的、使用C++编写的类加载器。
2. 默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等。

/*** 启动程序类加载器案例*/
public class BootstrapClassLoaderDemo {public static void main(String[] args) throws IOException {ClassLoader classLoader = String.class.getClassLoader();System.out.println(classLoader);System.in.read();}
}

这段代码通过String类获取到它的类加载器(Bootstrap)并且打印,结果是null。这是因为启动类加载器在JDK8中是由C++语言来编写的,在Java代码中去获取既不适合也不安全,所以返回null。

通过启动类加载器加载用户jar包

如果用户想扩展一些比较基础的jar包,并让启动类加载器加载,有以下两种途径。
1. 放入jre/lib下进行扩展(不推荐):尽可能不要去更改JDK安装目录中的内容,会出现即时放进去由于文件名不匹配的问题也不会正常地被加载;
2. 使用参数进行扩展(推荐):使用-Xbootclasspath/a:jar包目录/jar包名 进行扩展,参数中的/a代表新增。
如下图,在IDEA配置中添加虚拟机参数,就可以加载D:/jvm/jar/classloader-test.jar这个jar包了。


Extension扩展类加载器和Application应用程序类加载器

1. ClassLoader类定义了具体的行为模式,简单来说就是先从本地或者网络获得字节码信息,然后调用虚拟机底层的方法创建方法区和堆上的对象。这样的好处就是让子类只需要去实现如何获取字节码信息这部分代码;
2. SecureClassLoader提供了证书机制,提升了安全性;
3. URLClassLoader提供了根据URL获取目录下或者指定jar包进行加载,获取字节码的数据;
4. 扩展类加载器和应用程序类加载器继承自URLClassLoader,获得了上述的三种能力。

通过扩展类加载器加载用户jar包

1. 放入/jre/lib/ext下进行扩展(不推荐):尽可能不要去更改JDK安装目录中的内容;
2. 使用参数进行扩展使用参数进行扩展(推荐):使用-Djava.ext.dirs=jar包目录 进行扩展,这种方式会覆盖掉原始目录,可以用;(windows系统)或:(macos/linux系统)符号进行分隔追加上原始目录,如下图。

使用引号将整个地址包裹起来,这样路径中即便是有空格也不需要额外处理。路径中要包含原来ext文件夹,同时在最后加上扩展的路径。


双亲委派机制


面试题1:什么是双亲委派机制
1、当一个类加载器在加载某个类时,会先自底向上查找是否有加载器加载过,如果加载过就直接返回,如果一直到最顶层的类加载器都没有加载,再由顶向下进行加载;
2、应用程序类加载器的父类加载器是扩展类加载器,扩展类加载器的父类加载器是启动类加载器。

面试题2:双亲委派的作用/好处有哪些?
1.保证类加载的安全性。通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性;
2.避免重复加载。双亲委派机制可以避免同一个类被多次加载。

面试题3:如果一个类重复出现在三个类加载器的加载位置,应该由谁来加载?
答:由启动类加载器加载,根据双亲委派机制,它的优先级是最高的。

面试题4:String类能被覆盖吗,在自己的项目中创建一个java.lang.String类,会被加载吗?
不会,因为存在双亲委派机制,类不会被重复加载,会返回启动类加载器加载在rt.jar包中的String类。


打破双亲委派机制

打破双亲委派机制历史上有如下三种方式,但本质上只有第一种算是真正的打破了双亲委派机制。
1. 自定义类加载器并且重写loadClass方法。Tomcat通过这种方式实现应用之间类隔离;
2. 线程上下文类加载器。利用上下文类加载器加载类,比如JDBC和JNDI等;
3. Osgi框架的类加载器。历史上Osgi框架实现了一套新的类加载器机制,允许同级之间委托进行类的加载,目前很少使用。

自定义类加载器

        一个Tomcat程序中是可以运行多个Web应用的,如果这两个应用中出现了相同限定名的类,比如Servlet类,Tomcat就需要保证这两个类都能加载并且它们应该是不同的类。如果不打破双亲委派机制,当应用类加载器加载Web应用1中的MyServlet之后,Web应用2中相同限定名的MyServlet类就无法被加载了。
        那么自定义加载器是如何做到打破双亲委派机制的呢?首先我们需要了解双亲委派机制的代码到底在哪里,接下来只需要把这段代码消除即可。
        ClassLoader中包含了4个核心方法,双亲委派机制的核心代码就位于loadClass方法中。

//类加载的入口,提供了双亲委派机制。内部会调用findClass [重要]
public Class<?> loadClass(String name)//由类加载器子类实现,获取二进制数据调用defineClass
//比如URLClassLoader会根据文件路径去获取类文件中的二进制数据。[重要]
protected Class<?> findClass(String name)//做一些类名的校验,然后调用虚拟机底层的方法将字节码信息加载到虚拟机内存中
protected final Class<?> defineClass(String name, byte[] b, int off, int len)//执行类生命周期中的连接阶段
protected final void resolveClass(Class<?> c)

loadClass方法核心代码如下

//先查找是否加载过,加载过就返回
Class<?> c = findLoadedClass(name);//如果没有加载过,则委派给父类加载
if(c == null){//parent等于null则说明父类加载器是启动类加载器if(parent != null){c = parent.loadClass(name,false);//由父类加载elsec = findBootstrapClassOrNull(name);//由启动类加载器加载//若父类加载器无法加载,则由本加载器加载if(c == null)c = findClass(name);}return c;

自定义加载器通过重写 loadClass 方法,清除了其中有关双亲委派机制的逻辑,因此打破了双亲委派机制。
按照loadClass方法的逻辑,如果父类加载失败,会调用自己的findClass方法来完成类的加载。如果用户在实现自定义类加载器时,希望按照自己的意愿去加载类,但又想保证自定义类加载器是符合双亲委派机制的,则可以重写findClass方法,在该方法中实现类的加载逻辑,而不必重写loadClass方法,从而保留了双亲委派机制的逻辑。

自定义类加载器打破双亲委派机制代码如下

package classloader.broken;//package com.itheima.jvm.chapter02.classloader.broken;import org.apache.commons.io.IOUtils;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.ProtectionDomain;
import java.util.regex.Matcher;/*** 打破双亲委派机制 - 自定义类加载器*/public class BreakClassLoader1 extends ClassLoader {private String basePath;private final static String FILE_EXT = ".class";//设置加载目录public void setBasePath(String basePath) {this.basePath = basePath;}//使用commons io 从指定目录下加载文件private byte[] loadClassData(String name)  {try {String tempName = name.replaceAll("\\.", Matcher.quoteReplacement(File.separator));FileInputStream fis = new FileInputStream(basePath + tempName + FILE_EXT);try {return IOUtils.toByteArray(fis);} finally {IOUtils.closeQuietly(fis);}} catch (Exception e) {System.out.println("自定义类加载器加载失败,错误原因:" + e.getMessage());return null;}}//重写loadClass方法,不再走双亲委派机制@Overridepublic Class<?> loadClass(String name) throws ClassNotFoundException {//在加载默认的Object父类时,需要交由父类加载if(name.startsWith("java.")){return super.loadClass(name);}//从磁盘中指定目录下加载byte[] data = loadClassData(name);//调用虚拟机底层方法,方法区和堆区创建对象return defineClass(name, data, 0, data.length);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {//第一个自定义类加载器对象BreakClassLoader1 classLoader1 = new BreakClassLoader1();classLoader1.setBasePath("D:\\lib\\");Class<?> clazz1 = classLoader1.loadClass("com.itheima.my.A");//第二个自定义类加载器对象BreakClassLoader1 classLoader2 = new BreakClassLoader1();classLoader2.setBasePath("D:\\lib\\");Class<?> clazz2 = classLoader2.loadClass("com.itheima.my.A");System.out.println(clazz1 == clazz2);Thread.currentThread().setContextClassLoader(classLoader1);System.out.println(Thread.currentThread().getContextClassLoader());System.in.read();}
}

默认情况下自定义类加载器的父类加载器是应用程序类加载器。

两个自定义类加载器加载相同限定名的类,不会冲突吗?
不会冲突,在同一个Java虚拟机中,只有相同类加载器+相同的类限定名才会被认为是同一个类。


线程上下文类加载器

利用线程上下文类加载器加载类,比如JDBC和JNDI等,现对JDBC案例进行讨论,首先需要介绍java SPI机制。

Java SPI机制
定义:
SPI 是一种基于接口的编程模式,它允许服务提供者在不修改原有系统代码的情况下,通过实现特定接口并将其部署到应用程序的类路径下,从而被应用程序自动加载和使用。服务使用者只需定义接口规范并由服务提供者负责对接口进行实现,服务使用者不用关心具体的实现细节。这使得代码的维护和升级更加容易,降低了模块之间的耦合度。

Java SPI 的详细工作原理如下
1. 定义服务接口: 首先,定义一个接口,这个接口将作为服务的规范,规定所有实现类必须遵循的方法;
2. 实现服务接口: 接着,创建一个或多个接口实现类,每个实现类代表一个具体的服务提供者;
3. 注册服务实现: 在实现类的JAR 包中,创建一个 META-INF/services/ 目录,并在其中创建一个以服务接口全名命名的文件。文件内容包含实现类的全名,每行一个;
4. 加载和使用服务: 使用 ServiceLoader 类来加载这些服务实现。ServiceLoader 会查找 META-INF/services 目录中的服务定义,并加载所有实现类。

在 Java 中,数据库连接是一个典型的 SPI 应用场景。Java 的java.sql.Driver接口就是一个服务接口。不同数据库厂商(如 MySQL、Oracle、SQL Server 等)提供了各自的Driver实现类。
JDBC中使用了DriverManager来管理项目中引入的不同数据库的驱动,比如mysql驱动、oracle驱动。
DriverManager类由JDK提供,位于rt.jar包中,由启动类加载器加载。DriverManager类需要去加载服务提供者引入的jar包中的驱动类(SPI机制),而jar包中的驱动类需要委派应用程序类加载器去加载,这种父类加载器去请求子类加载器完成类的加载行为,打破了双亲委派机制。Java中涉及SPI的加载基本上都采用这种方式来完成。


Osgi框架的类加载器

历史上,OSGi模块化框架存在同级之间的类加载器的委托加载。OSGi还使用类加载器实现了热部署的功能。热部署指的是在服务不停止的情况下,动态地更新字节码文件到内存中。

以下内容节选自《深入理解 Java 虚拟机》
总结:在 OSGi 环境下,类加载器不再遵循双亲委派模型所推荐的树状结构,而是拥有一套自身的类加载规则,其中部分规则打破了类的双亲委派机制。


总结

在上述介绍的三种打破双亲委派机制的方式中,本质上只有第一种方式算是真正打破了该机制。这是因为双亲委派机制的核心代码在 loadClass 中,而只有第一种方式重写了 loadClass 方法,清除了其中有关双亲委派机制的逻辑。

至于其他两种方式,从宏观层面,也就是类的调用层面来看,违背了双亲委派机制。但这两种方式并没有重写loadClass方法,并未清除有关双亲委派机制逻辑的代码,所以从单个类的角度而言,是符合双亲委派机制的。


JDK9之后的类加载器

JDK8及之前的版本中,扩展类加载器和应用程序类加载器的源码位于rt.jar包中的sun.misc.Launcher.java。

由于JDK9引入了module的概念,类加载器在设计上发生了很多变化。
1.启动类加载器使用Java编写,位于jdk.internal.loader.ClassLoaders类中。
Java中的BootClassLoader继承自BuiltinClassLoader,实现从模块中找到要加载的字节码资源文件。启动类加载器依然无法通过java代码获取到,返回的仍然是null,保持了统一。

2、扩展类加载器被替换成了平台类加载器(Platform Class Loader)。
平台类加载器遵循模块化方式加载字节码文件,所以继承关系从URLClassLoader变成了BuiltinClassLoader,BuiltinClassLoader实现了从模块中加载字节码文件。平台类加载器的存在更多的是为了与老版本的设计方案兼容,自身没有特殊的逻辑。


文章转载自:
http://yugoslavic.c7497.cn
http://federalize.c7497.cn
http://discoid.c7497.cn
http://ultrasound.c7497.cn
http://elegise.c7497.cn
http://manhole.c7497.cn
http://fourplex.c7497.cn
http://reimprint.c7497.cn
http://spoliaopima.c7497.cn
http://evaporator.c7497.cn
http://oniomania.c7497.cn
http://prml.c7497.cn
http://ribose.c7497.cn
http://cesspipe.c7497.cn
http://tepa.c7497.cn
http://revolver.c7497.cn
http://redeliver.c7497.cn
http://caducei.c7497.cn
http://toadstone.c7497.cn
http://comandante.c7497.cn
http://haemoptysis.c7497.cn
http://infract.c7497.cn
http://cigala.c7497.cn
http://saddlebred.c7497.cn
http://electrodermal.c7497.cn
http://fingo.c7497.cn
http://parging.c7497.cn
http://naught.c7497.cn
http://ichthyosarcotoxism.c7497.cn
http://mien.c7497.cn
http://redbud.c7497.cn
http://varley.c7497.cn
http://matriculant.c7497.cn
http://conac.c7497.cn
http://countershaft.c7497.cn
http://piefort.c7497.cn
http://slavophobist.c7497.cn
http://geogony.c7497.cn
http://troglodyte.c7497.cn
http://seronegative.c7497.cn
http://inoxidize.c7497.cn
http://goanese.c7497.cn
http://catfall.c7497.cn
http://somatotrophic.c7497.cn
http://manila.c7497.cn
http://outstare.c7497.cn
http://huckaback.c7497.cn
http://medieval.c7497.cn
http://labdanum.c7497.cn
http://retrogressive.c7497.cn
http://procural.c7497.cn
http://arbour.c7497.cn
http://fomes.c7497.cn
http://final.c7497.cn
http://scolopophorous.c7497.cn
http://quaquversal.c7497.cn
http://monobloc.c7497.cn
http://mourn.c7497.cn
http://township.c7497.cn
http://placet.c7497.cn
http://diglottic.c7497.cn
http://portacaval.c7497.cn
http://argal.c7497.cn
http://incipit.c7497.cn
http://karsey.c7497.cn
http://plier.c7497.cn
http://peso.c7497.cn
http://comedones.c7497.cn
http://stipulation.c7497.cn
http://marking.c7497.cn
http://eloise.c7497.cn
http://shovelboard.c7497.cn
http://sarrusophone.c7497.cn
http://virid.c7497.cn
http://morgen.c7497.cn
http://cue.c7497.cn
http://vise.c7497.cn
http://strode.c7497.cn
http://supposition.c7497.cn
http://mechanise.c7497.cn
http://alpheus.c7497.cn
http://cart.c7497.cn
http://renard.c7497.cn
http://ghibli.c7497.cn
http://lemonish.c7497.cn
http://ynquiry.c7497.cn
http://masonite.c7497.cn
http://pepsinate.c7497.cn
http://secular.c7497.cn
http://undercart.c7497.cn
http://codetermine.c7497.cn
http://billiards.c7497.cn
http://anthodium.c7497.cn
http://extraordinaire.c7497.cn
http://suitability.c7497.cn
http://anticlockwise.c7497.cn
http://demoniacally.c7497.cn
http://pariahdom.c7497.cn
http://babblingly.c7497.cn
http://grammar.c7497.cn
http://www.zhongyajixie.com/news/77188.html

相关文章:

  • 网站内做营销活动使用工具seo辅助工具
  • 网站建设中中文模板下载高端网站定制设计
  • 新办公司网上核名在哪个网站做如何制作网站赚钱
  • html5基础宁波seo优化
  • 自动做网站特大新闻凌晨刚刚发生
  • 韩国优秀平面设计网站吉林seo排名公司
  • 大连网络营销seo课堂
  • 海东网站建设市场监督管理局上班时间
  • 代理网站开发义乌最好的电商培训学校
  • 网站怎么优化 优帮云惠东seo公司
  • 健身器材 网站模版线上销售平台都有哪些
  • 新冠疫苗最新官方消息网站优化排名推广
  • 网站建设心得体会800字seo定义
  • 合肥专业网站制作设计百度科技有限公司
  • 青岛网站制作价格看网站搜什么关键词
  • 网站台做计么呢新闻最新头条10条
  • 传媒公司 网站开发济南计算机培训机构哪个最好
  • 专门做美食的视频网站有哪些百度电话销售
  • 网站建设注意事项整合营销包括哪些内容
  • 微企免费做网站seo优化网站推广全域营销获客公司
  • 沧州百胜信息技术有限公司泰州seo排名扣费
  • wordpress提示更新英文吧seo体系
  • 网站优化两大核心要素是什么个人如何加入百度推广
  • 域名连接到网站怎么做关键词排名点击
  • 青岛公司网站制作优化大师是什么软件
  • 网站建设收费分几次网址域名
  • 网站建设的日程安排搜索百度网址网页
  • 评价高的企业网站开发2345网址导航官网官方电脑版
  • 广告公司做的网站图片侵权快速排名生客seo
  • php和django做网站哪个好长沙seo运营