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

赣州福泰龙网站建设东莞地铁线路图

赣州福泰龙网站建设,东莞地铁线路图,wordpress查询系统,制作自己的网页类加载机制 一、Java类加载机制 java中#xff0c;每一个类或者接口#xff0c;在编译后#xff0c;都会生成一个.class文件。 类加载机制指的是将这些.class文件中的二进制数据读入到内存中并对数据进行校验#xff0c;解析和初始化。最终#xff0c;每一个类都会在方…类加载机制 一、Java类加载机制 java中每一个类或者接口在编译后都会生成一个.class文件。 类加载机制指的是将这些.class文件中的二进制数据读入到内存中并对数据进行校验解析和初始化。最终每一个类都会在方法去保存一份元数据在堆中创建一个与之对应的Class对象。 类的生命周期经历7个阶段分别是加载验证准备解析初始化使用卸载。 类加载过程包括加载验证准备解析初始化 类加载时机 类加载时机也就是.class文件什么时候被读取到虚拟机的内存中并且达到可用的状态。 大多数情况下都遵循什么时候初始化来进行加载。 初始化时机 使用new实例化对象时读取或者设置一个类的静态字段或者方法时。反射调用时例如Class.forName(“com.xxx.ClassName”)初始化一个类的子类会首先初始化子类的父类Java虚拟机启动时标明的启动类JDK8之后接口中存在default方法这个接口的实现来初始化时接口会在其之前进行初始化。 类的加载过程 类的加载过程分5个阶段其中验证准备解析可以归纳为”连接“ **注**这五个阶段并不是严格意义上的按顺序完成在类加载过程中这些阶段会互相混合交叉运行最终完成类的加载和初始化。 加载 加载是类加载过程的第一个阶段在加载阶段虚拟机需要完成三件事情 通过类的全限定名去找到其对应的.class文件将这个.class文件内的二进制数据读取出来转化成方法区的运行时数据结构在java堆中生成一个代表这个类的java.lang.Class对象作为对方法去中这些数据的访问入口 验证 Class文件中的内容是字节码这些内容可以由任何途径产出验证阶段的目的是保证文件内容里边的字节流符合Java虚拟机规范且这些内容信息运行后不会危害虚拟机的自身的安全。 验证阶段会完成以下校验 文件格式校验验证字节码是否符合Class文件格式的规范 **元数据验证**对字节码描述的元数据信息进行语义分析要符合java语言规范 字节码验证对类的方法体进行校验确保这些方法在运行时是合法的符合逻辑的 符号引用验证发生在解析阶段符号引用转为直接引用的时候。 验证阶段是非常重要的但不是必须的对程序运行期没有影响如果在保证引用的类经过验证的情况下可以考虑使用-Xverifynone参数来关闭大部分的类验证措施以缩短虚拟机类加载的时间。 准备 准备阶段类的静态字段信息会得到内存分配并且被设置为初始值 1.内存分配仅包括static修饰过的变量而不包含实例变量实例变量得等到对象实例化的时候分配内存2.初始值指的是变量数据类型的默认值而不是被在java代码中显式赋予的值当字段被final修饰成常量时这个初始值就是java代码中显式赋予的值。 例如public static int value 3 类变量 value 在准备阶段设置的初始值是 0不是 3。把value赋值为3的 putstatic 指令是在程序编译后存放于类构造器 () 方法中的所以把 value 赋值为 3 的动作将在初始化阶段才会执行。 当使用 final 修饰后public static final int value 3 类变量 value 在准备阶段设置的初始值是 3不是 0。 3.在JDK取消永久代后方法区变成了一个逻辑上的区域这些类变量的内存实际上是分配在java堆中的。 解析 这个阶段虚拟机会把这个Class文件中常量池的符号引用转换为直接引用。主要解析的是类或者接口字段类方法接口方法方法类型方法句柄等符号引用。符号引用转换为直接应用的过程就是当前加载的这个类和它所引用的类正式进行连接的过程。 什么是符号引用 java代码在编译期间是不知道最终引用的类型具体指向内存中的哪个位置的此时会用一个符号引用来表示具体引用的目标是谁Java虚拟机规范中明确定义了符号引用的形式符合这个规范的前提下符号引用可以是任意值只要能通过这个值能定位到目标什么是直接引用 直接引用就是可以直接或者间接指向目标内存位置的指针或句柄 引用的类型还未加载初始化怎么办 当出现这种情况会触发这个引用对应类型的加载和初始化初始化 类加载的最后一步初始化的过程就是执行类构造器clinit()方法的过程 当初始化完成之后类中static修饰的变量会赋予程序员实际定义的值同时类中如果存在static代码块也会执行这个静态代码里边的代码 clinit()方法的作用是什么 在准备阶段已经对类中static修饰的变量赋予了初始值。clinit()方法的作用就是给这些变量赋予程序员实际定义的值。同时类中如果存在static代码块也会执行这个静态代码块里边的代码clinit方法是什么 clinit方法和init方法是不同的它们一个是类构造器一个是实例构造器java虚拟机会保证子类clinit方法在执行前父类的clinit已经执行完毕。而init方法则需要显性的调用父类的构造器 clinit()方法由编译器自动生成但不是必须生成的只有这个类存在static修饰的变量或者类中存在静态代码块的时候才会自动生成clinit方法加载过程总结 当一个符合java虚拟机规范的字节流文件经历加载验证准备解析初始化这些阶段相互协作完成之后加载阶段读取到的Class字节流信息会按虚拟机规定的格式在方法区保存一份然后会在java堆中会创建一个java.lang.Class类的对象这个对象描述了这个类所有信息也提供了这个类在方法区的访问入口。 方法区中使用同一加载器的情况下每个类只会有一份Class字节流信息 Java堆中使用同一加载器的情况下每个类中只会有一份java.lang.Class类的对象类加载器 类加载器就是在加载阶段通过类的全限定名获取该类字节流数据的动作。 三层类加载器介绍 启动类加载器Bootstrap Class Loader负责加载JAVA_HOME\lib目录或者呗-Xbootclasspath参数指定的路径例如jre/lib/rt.jar里所有的class文件。由c实现不是ClassLoader子类拓展类加载器Extension Class Loader负责加载Java平台中扩展功能的一些jar包包括JAVA_HOME\lib\ext目录中或者java.ext.dirs指定目录下的jar包由java代码实现。应用程序类加载器Application Class Loader程序开发者开发的应用程序有他加载负责加载ClassPath路径下的所有jar包 双亲委派模型 任何一个类加载器在接到一个类的加载请求时都会先让其父类进行加载只有父类无法加载或者没有父类的情况下才尝试加载 protected Class? loadClass(String name, boolean resolve)throws ClassNotFoundException{// First, check if the class has already been loadedClass? 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) {// If still not found, then invoke findClass in order// to find the class.c findClass(name);}}return c;}ClassLoader类中的加载示例 双亲委派模型的好处 使用双亲委派模型可以保证每一个类只会有一个类加载器例如java最基础的Object类它存放在rt.jar中这是Bootstrap的职责范围当向上委派到Bootstrap时就会被加载但是如果没有双亲委派模型可以任由自定义类加载器加载的话Java的核心api就会被随意篡改 二、Android中的ClassLoader 1、类加载器类型 Android跟java有很大的渊源基于jvm的java应用是通过classLoader来加载应用中的class的Android对jvm优化过使用的是dalvik虚拟机且class文件会被打包进一个dex文件中底层虚拟机有所不同那么它们的类加载器也会有区别。 Andorid中最主要的类加载器有4个 BootClassLoader: 加载Android Framework层的class字节码文件类似java的BootStrapClassLoaderPathClassLoader: 加载已经安装到系统中的APK的class字节码文件类似java的App ClassLoaderDexClassLoader:加载指定目录的class字节码文件类似java中的Custom ClassLoader Android 中的类加载器和java类加载器一样使用的是双亲委派模型 2、PathClassLoader与DexClassLoader的区别 1使用场景 PathClassLoader: 只能加载已经安装到Android系统的apk文件data/app目录是Android默认使用的类加载器DexClassLoader可以加载任意目录下的dex/jr/zip文件比PathClassLoader更灵活 2代码差异 // PathClassLoader public class PathClassLoader extends BaseDexClassLoader {public PathClassLoader(String dexPath, ClassLoader parent) {super(dexPath, null, null, parent);}public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {super(dexPath, null, librarySearchPath, parent);} } // DexClassLoader public class DexClassLoader extends BaseDexClassLoader {public DexClassLoader(String dexPath, String optimizedDirectory,String librarySearchPath, ClassLoader parent) {super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);} } PathClassLoader与DexClassLoader都继承于BaseDexClassLoaderPathClassLoader与DexClassLoader在构造函数中都调用了父类的构造函数但DexClaccLoader多传了一个optimizeDirectory 3、BaseDexClassLoader 1) 构造函数 public class BaseDexClassLoader extends ClassLoader {private final DexPathList pathList;...public BaseDexClassLoader(String dexPath, File optimizedDirectory, String libraryPath, ClassLoader parent){super(parent);this.pathList new DexPathList(this, dexPath, libraryPath, optimizedDirectory);}... } dexPath:要加载的程序文件一般是dex文件也可以是jar/apk/zip文件所在目录optimizedDirectory:dex文件的输出目录因为在加载jar/apk/zip等压缩格式的文件时会解压出其中的dex文件该目录就是专门用于存放这些被解压出来的dex文件liraryPath加载程序文件时需要用到的库路径parent:父加载器 pathClassLoader只会加载已安装包中的dex文件而dexClassLoader不仅仅可以加载dex文件还可以加载jar,apk,zip中的dex。jar apk zip就是一些压缩格式要拿到压缩包里边的dex文件就需要解压。所以DexClassLoader在调用父构造函数时会指定一个解压目录 2 findClass() 类加载器会提供一个方法来供外界找到它所加载的class,该方法就是findClass()。 private final DexPathList pathList;Override protected Class? findClass(String name) throws ClassNotFoundException {ListThrowable suppressedExceptions new ArrayListThrowable();// 实质是通过pathList的对象findClass()方法来获取classClass c pathList.findClass(name, suppressedExceptions);if (c null) {ClassNotFoundException cnfe new ClassNotFoundException(Didnt find class \ name \ on path: pathList);for (Throwable t : suppressedExceptions) {cnfe.addSuppressed(t);}throw cnfe;}return c; } 可以看到BaseDexClassLoader的findClass()方法实际上是通过DexPathList对象的findClass()方法来获取class,而这个DexPathLIst对象恰好在之前的BaseDexClassLoader构造函数中就已经被创建好了。 4.DexPathList 1 构造函数 private final Element[] dexElements;public DexPathList(ClassLoader definingContext, String dexPath,String libraryPath, File optimizedDirectory) {...this.definingContext definingContext;this.dexElements makeDexElements(splitDexPath(dexPath), optimizedDirectory,suppressedExceptions);... } 构造函数中保存了当前类加载器definingContext并调用的makeDexElements()得到Element集合 通过对splitDexPath(dexPath)的源码追溯发现该方法的作用其实就是将dexPath目录下的所有程序文件转变成一个File集合。而且还发现dexPath是一个用冒号“:”作为分隔符把多个程序文件目录拼接起来的字符串(如/data/dexdir1:/data/dexdir2:…)。 makeDexElements()方法 private static Element[] makeDexElements(ArrayListFile files, File optimizedDirectory, ArrayListIOException suppressedExceptions) {// 1.创建Element集合ArrayListElement elements new ArrayListElement();// 2.遍历所有dex文件也可能是jar、apk或zip文件for (File file : files) {ZipFile zip null;DexFile dex null;String name file.getName();...// 如果是dex文件if (name.endsWith(DEX_SUFFIX)) {dex loadDexFile(file, optimizedDirectory);// 如果是apk、jar、zip文件这部分在不同的Android版本中处理方式有细微差别} else {zip file;dex loadDexFile(file, optimizedDirectory);}...// 3.将dex文件或压缩文件包装成Element对象并添加到Element集合中if ((zip ! null) || (dex ! null)) {elements.add(new Element(file, false, zip, dex));}}// 4.将Element集合转成Element数组返回return elements.toArray(new Element[elements.size()]); } 总体来说DexPathList的构造函数是将一个个的程序文件可能是dex、apk、jar、zip封装成一个个Element对象最后添加到Element集合中。 Android的类加载器不管是PathClassLoader还是DexClassLoader它们最后只认dex文件而loadDexFile()是加载dex文件的核心方法可以从jar、apk、zip中提取出dex 2) findClass() DexPathList的findClass()方法 public Class findClass(String name, ListThrowable suppressed) {for (Element element : dexElements) {// 遍历出一个dex文件DexFile dex element.dexFile;if (dex ! null) {// 在dex文件中查找类名与name相同的类Class clazz dex.loadClassBinaryName(name, definingContext, suppressed);if (clazz ! null) {return clazz;}}}if (dexElementsSuppressedExceptions ! null) {suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));}return null; } DexPathList的findClass()方法很简单就只是对Element数组进行遍历一旦找到类名与name相同的类时就直接返回这个class找不到则返回null。 调用DexFile的loadClassBinaryName()方法来加载class这是因为一个Element对象对应一个dex文件而一个dex文件则包含多个class。也就是说Element数组中存放的是一个个的dex文件而不是class文件。这可以从Element这个类的源码和dex文件的内部结构看出。 android类加载器与java类加载器异同 根据前面的分析我们总结下android与java在类加载上的异同 相同 Android类加载器和Java的类加载器工作机制是类似的使用双亲委托机制 不同 加载的字节码不同 Android虚拟机运行的是dex字节码Java虚拟机运行的class字节码。类加载器不同以及类加载器的类体系结构不同 如上面的类加载器结构图BootClassLoader和Java的BootStrapClassLoader区别Android虚拟机中BootClassLoader是ClassLoader内部类由java代码实现而不是c实现是Android平台上所有ClassLoader的最终parent这个内部类是包内可见,所以我们没法使用。 Java虚拟机中BootStrapClassLoader是由原生代码(C)编写的负责加载java核心类库(例如rt.jar等)ClassLoader类中的findBootstrapClassOrNull方法android sdk直接返回nulljdk会去调用native方法findBootstrapClass如下源码
http://www.yayakq.cn/news/5080/

相关文章:

  • 企业网站建设的请示可以自己做漫画的软件
  • 织梦做的网站 xampp成都网站建设 四川冠辰
  • 郑州那个公司做网站好wordpress菜单下拉菜单
  • 微信分销小程序开发新乡百度网站优化排名
  • 还是网站好备案空壳网站
  • 融资网站建设wordpress 合同
  • 武平县天恒建设投资集团公司网站星际网络泰安网络公司
  • 广州专业做网站公司有哪些电脑优化是什么意思
  • 四川建设网站公司wordpress是不是做网页
  • 项目网站建设业务分析企业管理官网登录入口
  • 国外网站建设素材库上海做网站的公司有哪些
  • 办公室装修设计招商seo优化专员编辑
  • 招聘门户网站开发人员做做网站下载2023
  • 什么样的网站快速盈利做网页设计需要学什么
  • 安庆网站关键词优化天津网站设计公司
  • wordpress 下载站模板在网站设计公司上班好吗
  • 怎么让自己做的网站别人可以访问网站定制首页费用
  • 花生壳内网穿透网站如何做seo优化学校网站建设工作领导小组
  • 网站设计结构图用什么做青岛煜鹏网站建设公司
  • 宁津县建设局网站wordpress邮件发送
  • 软件技术跟网站开发有关系吗中企建设网站
  • 网站推广的主要方法天津城乡住房建设厅网站首页
  • 自己的网站是什么样子的东莞有哪些公司
  • 南阳网站建设报价怎么做网站适配
  • 邵阳建设网站公司电子业网站建设
  • 电商网站页面布局河田镇建设局网站
  • 女生自己做网站wordpress公众号采集
  • 企业网站建完后没人重庆网站关键词优化推广
  • 深圳市专业做网站小程序登录不上什么原因
  • 江苏建设一体化平台网站职业技能证书查询入口