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

最好在线网站建设沙漠风网站建设公司

最好在线网站建设,沙漠风网站建设公司,江苏网站建设方案,腾讯企业邮箱注册申请官网文章目录1 什么是类加载1.1 类加载的应用1.2 类加载过程1.3 类的验证1.4 类初始化顺序2 类加载时机3 类加载器3.1 类加载分类3.2 双亲委派3.3 自定义类加载器3.4 类加载器的命名空间4 打破双亲委派4.1 线程上下文类加载器4.2 自定义类加载器5 类的卸载1 什么是类加载 Java 虚拟… 文章目录1 什么是类加载1.1 类加载的应用1.2 类加载过程1.3 类的验证1.4 类初始化顺序2 类加载时机3 类加载器3.1 类加载分类3.2 双亲委派3.3 自定义类加载器3.4 类加载器的命名空间4 打破双亲委派4.1 线程上下文类加载器4.2 自定义类加载器5 类的卸载1 什么是类加载 Java 虚拟机把描述类的数据从 Class 文件加载到内存并对数据进行校验、转换解析和初始化最终形可以被虚拟机直接使用的 Java 类型这个过程被称作虚拟机的类加载机制。 1.1 类加载的应用 在 Java 中类型的加载、连接和初始化过程都是在程序运行期间完成的为 Java 应用提供了极高的扩展性和灵活性例如编写一个面向接口的应用程序可以等到运行时再指定其实际的实现类例如下面会提到的 SPI 机制通过Java预置的或自定义类加载器让某个本地的应用程序在运行时从网络或其他地方上加载一个二进制流作为其程序代码的一部分JSP、字节码增强。 1.2 类加载过程 在 Java 中一个类从定义到使用可以分为加载、验证、准备、解析、初始化、使用以及卸载几个步骤。其中验证、准备和解析又可以统称为连接。 加载通过全限定类名查找并加载类的二进制数据将静态存储结构转化为方法区的运行时数据结构java.lang.Class 对象验证确保被加载的类的正确性准备为类的静态变量分配内存并将其初始化为默认值解析把类中的符号引用转换为直接引用初始化为类的静态变量赋予正确的初始 1.3 类的验证 验证是连接阶段的第一步这一阶段的目的是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求并且不会危害虚拟机自身的安全。 1文件格式验证此阶段保证输入的字节流能正确地解析并存储于方法区之内格式上符合描述一个 Java 类型信息的要求。如是否以魔数 0xCAFEBABE 开头主、次版本号是否在当前虚拟机处理范围之内常量合理性验证等。 2元数据验证此阶段保证不存在不符合 Java 语言规范的元数据信息。如是否存在父类父类的继承链是否正确抽象类是否实现了其父类或接口之中要求实现的所有方法字段、方法是否与父类产生矛盾等。 3字节码验证通过数据流和控制流分析确定程序语义是合法的、符合逻辑的。例如保证跳转指令不会跳转到方法体以外的字节码指令上。 4符号引用验证在解析阶段中发生保证可以将符号引用转化为直接引用。 可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施以缩短虚拟机类加载的时间。 1.4 类初始化顺序 父类静态变量/静态初始化块 - 子类静态变量/静态初始化块父类变量/初始化块 - 父类构造器子类变量/初始化块 - 子类构造器。 2 类加载时机 JVM 规范并未对何时进行类加载过程进行强制约束但 JVM 规范严格规定了有且只有六种情况必须立即对类进行“初始化”同时保证在此之前完成加载、验证、准备这六种场景称之为对类的主动使用 遇到 new、getstatic、putstatic 或 invokestatic 这四条字节码指令时如果类型没有进行过初始化则需要先触发其初始化阶段使用 java.lang.reflect 包的方法对类型进行反射调用的时候如果类型没有进行过初始化则需 要先触发其初始化当初始化类的时候如果发现其父类还没有进行过初始化则需要先触发其父类的初始化当虚拟机启动时用户需要指定一个要执行的主类包含 main() 方法的那个类虚拟机会先初始化这个主类当使用 JDK 7 新加入的动态语言支持时如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四种类型的方法句柄并且这个方法句柄对应的类没有进行过初始化则需要先触发其初始化当一个接口中定义了 JDK 8 新加入的默认方法被 default 关键字修饰的接口方法时如果有这个接口的实现类发生了初始化那该接口要在其之前被初始化。 除此之外所有引用类的方式都不会触发初始化称为被动引用如 通过子类引用父类的静态字段不会导致子类初始化。通过数组定义来引用类不会触发此类的初始化。MyClass[] cs new MyClass[10];常量在编译阶段会存入调用类的常量池中本质上并没有直接引用到定义常量的类因此不会触发定义常量的类的初始化。 3 类加载器 JVM 团队有意将通过一个类的全限定名来获取描述该类的二进制字节流这个动作放到 JVM 之外实现以方便程序积极决定如何获取所需要的类。即实现这一动作的代码被称之为类加载器ClassLoader。 3.1 类加载分类 类加载器可以分为两种类型分别是虚拟机自带类加载器和用户自定义类加载器。当 JVM 启动时会自顶向下形成会形成由三个类加载器组成的初始类加载器层次结构 启动类加载器BootstrapClassLoader是嵌在 JVM 内核中的加载器该加载器是用 C 语言编写主要负载加载 JAVA_HOME/lib 下的类库启动类加载器无法被应用程序直接使用。扩展类加载器ExtensionClassLoader该加载器器是用 JAVA 编写且它的父类加载器是 Bootstrap。主要加载 JAVA_HOME/lib/ext 目录中的类库。也可通过 -Djava.ext.dirs 参数设置加载路径。应用程序类加载器AppClassLoader负责加载应用程序 classpath 目录下的所有 jar 和 class 文件。它的父加载器为 ExtClassLoader。 3.2 双亲委派 如果一个类加载器收到了类加载的请求它首先不会自己去尝试加载这个类而是把这个请求委派给父类加载器去完成每一个层次的类加载器都是如此因此所有的加载请求最终都应该传送到最顶层的启动类加载器中只有当父加载器反馈自己无法完成这个加载请求在该类加载的搜索范围中没有找到所需的类时子加载器才会尝试自己去完成加载。 看下ClassLoader#loadClass()方法的就能明白 Classloader 是如何通过组合父加载器 来实现双亲委托模型的了 protected Class? loadClass(String name, boolean resolve) {synchronized (getClassLoadingLock(name)) {// 首先检查类是否已加载Class? c findLoadedClass(name);if (c null) {// 先尝试通过该加载器的父加载器或启动类加载器加载try {if (parent ! null) {c parent.loadClass(name, false);} else {c findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c null) {// 如果还找不到调用findClass查找类c findClass(name);}}// 如果是true的话将该加载器链接到加载的类if (resolve) {resolveClass(c);}return c;} }3.3 自定义类加载器 实现自定义类加载器一般分为两步一是继承 java.lang.ClassLoader二是重写父类的 findClass() 方法。除此以外还有两个比较重要的方法 defineClass()将一个字节数组转换为 Class 类的实例loadClass()根据全限定类名找到类推荐自定义类加载器重写findClass()而不是当前方法。 实际上即使我们按如上方法自定义了类加载器也无法使用自定义类加载器。分析内部调用父类的无参构造函数 super() protected ClassLoader() {this(checkCreateClassLoader(), null, getSystemClassLoader()); }不难发现当我们实例化一个自定义类加载器的时候如果没有显示指定其父类加载器默认会使用系统应用类加载器作为其父类加载器又因为双亲委派模型的存在自定义类加载器会先使用其父类加载器(即AppClassLoader)去加载而我们自定义类 MyClass是在 classpath 下的系统类加载器能加载到所以最终MyClass的类加载器就是系统类加载器。 为了解决此问题可以冲几个方面入手 重写 loadClass() 方法打破双亲委派模型指定自定义类加载器的父类加载器将需要加载的 class 字节码文件移出父类加载器的扫描范围。 3.4 类加载器的命名空间 对于任意一个类都必须由加载它的类加载器和这个类本身一起共同确立其在 Java 虚拟机中的唯一性每一个类加载器都拥有一个独立的类名称空间。 同时父子类加载器命名空间之间存在一定的可见性关系。 同一个命名空间内的类是相互可见的子加载器的命名空间包含所有父加载器的命名空间因此由子加载器加载的类能看见父加载器加载的类例如系统类加载器加载的类能看见启动类加载器加载的类由父加载器加载的类不能看见子加载器加载的类如果两个加载器之间没有直接或间接的父子关系那么它们各自加载的类相互不可见通过两个自定加载类对同一个字节码文件加载生成的 Class 对象的 hashCode 是不同的。 4 打破双亲委派 4.1 线程上下文类加载器 通常情况下线程执行到某个类的时候只能看到这个类对应加载器所加载的类。即每个类都会使用自己的类加载器加载自身的类加载器来去加载其它类指所依赖的类如果classX 引用了 classY那么 classX 的类加载器就会去加载classY前提是classY 尚余被加载。 JDK 1.2 引入线程上下文类加载器Thread 提供getContextClassLoader() 与setContextClassLoader() 两个方法如果没有通过 setContextClassLoader 进行设置的话线程将继承其父线程的上下文类加载器Java 应用运行时的初始线程的上下文类加载器是应用程序类加载器AppClassLoader在线程中运行的代码可以通过该类加载器来加载类与资源。 SPI (Service Provider Interface) 机制就是一个 JAVA 中使用线程上下文类加载器比较典型的例子是 JAVA 提供的可用于第三方实现和扩展的机制。JDK 定义接口规范各个厂商根据接口规范实现。接口定义是在 JAVA 核心库中由启动类加载器加载上面我们提到一个类都会使用加载自己的类加载器去加载引用的类而这些接口的实现却来自于不同的 jar 包放在 classpath 下对启动类加载器是不可见的这样传统的双亲委托模型就无法满足SPI 的要求。需要 JAVA 核心类通过线程上下文类加载器通常是 AppClassLoader去加载不同的厂商的实现类。通过在 jar 包下的 META-INF/services/xxx要实现的接口文件中声明该接口的实现类就可以通过 ServiceLoader.load(xxx.class) 扫描到然后加载该类。 ref 真正理解线程上下文类加载器多案例分析) 4.2 自定义类加载器 使用自定义类加载器重写 loadClass() 方法注意不是 findClass() 方法。 但需要注意过滤类名放过需要加载的 JAVA 核心类如 java.lang.Object因为这些类无法使用自定义的类加载器加载。 5 类的卸载 JVM 规范中提到可以不要求虚拟机在方法区中实现垃圾收集因为方法区垃圾收集的“性价比”通常也是比较低的。判定一个类型是否属于“不再被使用的类”的条件就比较苛刻了。需要同时满足下面三个条件: 该类所有的实例都已经被回收Java堆中不存在该类及其任何派生子类的实例加载该类的类加载器已经被回收这个条件除非是经过精心设计否则通常是很难达成的该类对应的java.lang.Class对象没有在任何地方被引用无法在任何地方通过反射访问该类的方法。 当满足了类卸载的条件后通过Full GC便可执行类卸载回收方法区空间。
http://www.dnsts.com.cn/news/235204.html

相关文章:

  • 麓谷网站建设公司网站建设的利润
  • 网站建设 方案 评价表自己可以建设网站吗
  • 可以做网站的电脑软件手机端网站的区别
  • 南宁本地网站有哪些哪些网站做外链
  • 网站建设适合什么单位北京微网站建设设计服务公司
  • 网站用什么建设电力网站怎么做
  • 怎样打开网站如何做移动支付网站
  • 深圳机票网站建设蓝顿长沙网站制作公司
  • 做电工的有接单的网站吗汕头公众号开发公司
  • 学校网站建设需求分析调研表郑州网络推广招聘
  • 静态网页制作网站wordpress主题站
  • 集团网站建设详细策划怎样做自己的个人网站
  • flash网站制作单选框和复选框ui组件赣州推广平台
  • 网站建设建议书网页制作与设计考试
  • 企业网络推广做网站推广公司网站模板制作与安装教程
  • 网站开发 创造收益腾讯公司开发的软件有哪些
  • 怎样在门户网站做网络推广中国城乡住房和城乡建设部网站
  • 深圳龙岗淘宝网站建设公司有哪些网站与客户端的区别
  • 深圳商城网站公司腾讯云网站安全认证
  • 网站权重分析网站建设意见建议表
  • 找工程做在哪个网站?做语音聊天网站要多少钱
  • 网站如何运营维护全国网站建设公司排行版
  • 青岛网站建设搭建推荐一些高清1080p的浏览器
  • 丹东网站优化网站开发团队 人员
  • 郑州做订货网站制作网站app
  • 众希网站建设网页制作作业代码
  • 做网站需要哪些东西行政审批服务中心
  • 怎么用网页制作一个网站腾讯云 云服务器
  • 网站建设的技术支持2017我们一起做网站
  • 北京网站托管网站建设价钱差异