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

手机移动端网站案例国家企业营业执照查询系统

手机移动端网站案例,国家企业营业执照查询系统,seo官网优化,建立个公司网站JVM类加载机制 类加载 ​ 在JVM虚拟机实现规范中#xff0c;通过ClassLoader类加载把*.class字节码文件#xff08;文件流#xff09;加载到内存#xff0c;并对字节码文件内容进行验证#xff0c;准备#xff0c;解析和初始化#xff0c;最终形成可以被虚拟机直接使用…JVM类加载机制 类加载 ​ 在JVM虚拟机实现规范中通过ClassLoader类加载把*.class字节码文件文件流加载到内存并对字节码文件内容进行验证准备解析和初始化最终形成可以被虚拟机直接使用的java.lang.Class对象这个过程被称作类加载 ​ 类是在运行期间第一次使用时被类加载器动态加载至JVM。JVM不会一次性加载所有类。因为如果一次性加载那么占用很多的内存 类的生命周期 类的声明周期包括一下7个阶段 加载验证准备解析初始化使用卸载 结束类生命周期的几种场景 执行System.exit()方法程序正常执行结束程序执行中遇到了异常或错误而异常终止操作系统出现错误或强制结束程序而导致JVM虚拟机进程终止 类加载过程 类加载过程包括加载、验证、准备、解析和初始化 可以通过一句谐音来记忆“家宴准备了西式菜”家加载宴验证准备准备了西解析式初始化菜 加载 ​ 在加载阶段JVM主要完成以下三件事 通过类的完全限定名称获取定义该类的 *.class 字节码文件的二进制字节流将该字节流表示的静态存储结构转换为Metaspace元空间区的运行时存储结构。在内存中生成一个代表该类的 class对象作为元空间区中该类各种数据的访问入口。 由于 JVM 虚拟机对加载*.class字节码文件的来源并未做限制所以出现了以下的 *.class 字 节码文件加载方式 本地文件系统直接读取 从网络中通过服务器响应读取。例如: web Applet 技术 从 JAR 、 EAR 、 WAR 等压缩文件中读取 运行时通过动态代理技术生成字节码文件。例如: 在 java.lang.reflect.Proxy 使用 ProxyGenerator.generateProxyClass 的代理类的二进制字节流 由其他文件或容器生成。例如: 由tomcat将*.jsp文件翻译成 *.java 文件后编译生成对应的.Class字节码文件 ​ 在加载阶段完成之后*.class字节码文件的类信息数据就会存储在元空间同时在JVM虚拟机堆中生成一个该类的Class对象 验证 ​ 在验证阶段JVM主要确保*.class字节码文件中包含的信息复合当前虚拟机的要求并不会危害虚拟机的安全 ​ 验证阶段会完成下面四个阶段的检验 **文件格式验证**验证字节流是否符合*.class字节码文件 格式的规范且能被当前版本的虚拟机处理 是否以魔法数0xCAFEBABE开头主、次版本号是否在当前虚拟机处理范围之内常量池的常量中是否有不被支持的常量类型(检查常量tag标志)指向常量的各种索引值中是否有指向不存在的常量或不符合装型的常量CONSTANT Utf8 info 型的常量中是否有不符合 UTF8编码的数据*.class文件中各个部分及文件本身是否有被删除的或附加的其他信息 **元数据验证**对字节码描述的信息进行语义分析以保证其描述的信息符合Java语言规范的要求 这个类是否有父类除了java.lang.Object之外所有的类都应该有父类这个类的父类是否继承了不允许被继承的类(被final修饰的类)如果这个类不是抽象类是否实现了其父类或接口之中要求实现的所有方法类中的字段方法是否与父类产生了矛盾例如覆盖了父类的final字段出现不符合规定的方法重载例如方法参数都一致但返回值类型却不同等 **字节码验证**通过数据流和控制流分析确保程序语义是合法的符合逻辑的 保证跳转指令不会跳转到方法体以外的字节码指令上保证方法体中的类型转换是有效的例如: 可以把子类对象赋值给父类数据装型这是安全的;但把父类对象意赋值给子类数据类型甚至把对象赋值给毫无继承关系、完全不相千的一个数据类型则是危险和不合法的保证任意时刻操作数栈的数据装型与指令代码序列都能配合工作例如: 不会出现在操作栈中放置了一个int类型的数据,使用时却按long类型来加载入本地变量表中 **符号引用验证**生在虚拟机将符号引用转化为直接引用的时候这个转化动作将在连接的第三个阶段一一解析阶段中发生。确保解析动作能正常执行。 符号引用中通过字将串描述的全限定名是否能找到对应的类在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段符号引用中的类、字段和方法的访问性( private 、default、protected、public)是否可被当前类访问 为什么需要验证 ​ Java语言本身是相对安全的语言但*.class字节码文件并不一定要求用Java源码编译而来可以使用任何途径甚至可以用十六进制编译器直接编写来产生*.class字节码文件 ​ 类的加载是 JVM 针对 *.class 字节码文件的读取加载机制所以虚拟机如果不检查输入的字节流可能会因为载入了有害的字节流而导致系统崩溃所以验证是虚拟机对自身保护的一项重要工作。 ​ 另外通过类加载机制的验证环节可以增强解释器的运行期执行性能。因为解释器在运行期间无需再对每条执行指令进行检查。 准备 类变量是被static修饰的变量准备阶段为类变量分配内存并设置初始值使用的是元空间区的内存实例变量不会在这阶段分配内存它会在对象实例化时随着对象一起被分配在堆中。应该注意到实例化不是类加载的一个过程类加载发生在所有实例化操作之前且类加载只执行一次实例化可以进行多次初始值一般为0值 例如下面的类变量value被初始化为0而不是123 public static int value 123;如果类变量是常量那么它将初始化为表达式所定义的值不是0 例如下面的常量value被初始化为123而不是0 public static final int value 123;解析 ​ 将常量池的符号引用替换为直接引用。就是把常量池中值的地址直接替换为值 初始化 初始化阶段才真正开始执行类中定义的 Java 程序代码。初始化阶段是虚拟机执行类构造器clinit()方法的过程。在准备阶段类变量已经赋过一次系统要求的初始值而在初始化阶段根据程序员通过程序指定的主观计划去初始化类变量和其他资源 clinit()是由编译器自动收集类中所有类变量的赋值动作和静态语句块中的语句合并产生的编译器收集的顺序由语句在源文件中出现的顺序决定。所以静态语句块只能访问到定义在它之前的类变量定义在它之后的类变量只能赋值不能访问 例如以下代码中静态变量i只能赋值不能访问因为i定义在静态代码块的后开你 public class Test{static{i0; // 给变量赋值可以正常编译通过System.out.print(1);// 这句编译器会提示“非法向前引用”}static int i 1; }由于父类的clinit()方法先执行也就意味着父类中定义的静态语句块的执行要优先于子类。例如下面代码 public class Parent{public static int A 1 ;static {A2;}static class Sub extends Parent{public static int BA;}public static void main(String[] args){System.out.println(Sub.B); // 2} }clinit线程安全 ​ 虚拟机会保证一个类clinin()方法在多线程环境下被正确的加锁和同步如果多个线程同时初始化一个类只会有一个线程执行这个类clinit()方法其他线程都会阻塞等待直到活动线程执行clinit()方法完毕。如果在一个类的clinit()方法中有耗时的操作就可能造成多个线程阻塞在实际过程中该阻塞非常隐蔽几乎不会被察觉 类加载的时机 主动引用 虚拟机规范中并没有强制约束何时进行加载但是规范严格规定了只有下列六种情况必须对类进行加载: 当遇到new、getstatic、putstatic、invokestatic这4条字节码指令时比如new一个对象读取一个静态字段未被final修饰、或调用一个类的静态方法时 当 jvm 执行 new指令时会加载类。即: 当程序创建一个类的实例对象当 jvm 执行 getstatic 指今时会加载类。即: 程访问类的静态变量(不是静态常量常量会被加载到运行时常量池)。当 jvm 执行 putstatic 指令时会加载类。即: 程序给类的静态变量赋值当 jvm 执行invokestatic指令时会加载类。即: 程序调用类的静态方法 使用 java.lang.reflect 包的方法对类进行反射调用时如Class.forname(...) ,或 new Instance()等等。如果类没初始化需要触发类的加载 加载一个类如果其父类还未加载则先触发该父类的加载 当虚拟机启动时用户需要定义一个要执行的主类(包含 main() 方法的类)虚拟机会先加载这个类 当一个接口中定义了 JDK8 新加入的默认方法 (被 default 关键字修饰的接口方法)时如果有这个接口的实现类发生了加载则该接口要在实现类之前被加载 被动引用 ​ 除主动引用之外所有引用类的方式都不会触发加载成为被动引用 被动引用常见的例子包括 通过子类引用父类的静态字段不会导致子类加载 System.out.println(SubClass.value); // value字段在SubClass类的父类中定义通过数组定义引用类不会触发此类的加载。该过程会对数组进行加载数组类是一个由虚拟机自动生成的直接继承自Object的子类其中包含了数组的属性和方法 SuperClass[] sca new SuperClass[10];常量在编译阶段会存入调用类的常量池本质上没有直接引用到定义常量的类因此不会触发定义常量的类的加载 System.out.println(ConstClass.HELLOWORLD);类加载器 类加载器 在类加载过程的加载阶段通过类的完全限定名获取描述 类的二进制流的实现类被称为“类加载器” 类加载器分类 从JVM虚拟机的角度来讲只存在两种不同的类加载器 **启动类加载器**使用C实现是虚拟机的一部分**其他类的加载器**使用java实现独立于虚拟机继承自抽象类java.lang.ClassLoader 从Java开发人员的角度来看类架子啊其可以划分得更细致一些 启动类加载器 类加载器负责将存放在 JRE_HOME \ lib目录中的或者被 -Xbootclasspath 参数所指定的路径中的并且是虚拟机识别的(仅按照文件名识别如 rt.jar 名字不符合的类库即使放在 ib 目录中也不会被加载)类库加载到虚拟机内存中。例如java.util.*,java.io.** java.lang.* 类等常用基础库都是由启动类加载器加载。启动类加载器无法被 java程序直接引用。 扩展类加载器 该类加载器是由 ExtClassLoader ( sun.misc.Launcher$ExtclassLoader ) 实现负责将 JRE HOME/lib/ext 或者被 java.ext.dir 系统变量所指定路径中的所有类库加载到内存中例如 swing 系列、内置的 js引擎、xm 解析器等以 javax 开头的扩展类库都是由扩展类加载器加载开发者可以直接使用扩展类加载器。 应用程序类加载器 类加载器是由 AppclassLoadersun.misc.Launcher$AppclassLoader ) 实现。由于这个类加载器是 ClassLoader 中的 getSystemclassLoader() 方法的返回值因此也被称为系统类加载器。它负责加载用户类路径 ( ClassPath ) 上所指定的类库比如: 我们自己编写的自定义类或第三方 jar 包。开发者可以直接使用这个类加载器如果应用程序中没有自定义过自己的类加载器一般情况下这个就是程序中默认的类加载器 什么情况下需要自定义类加载器 隔离加载类。在某些框架内进行中间件与应用的模块之间进行隔离把类加载到不同的环境修改类加载方式扩展加载源。比如: 从数据库、网络、电视机顶盒进行类加载防止源码泄漏。比如: 编译时字节码进行加密需要通过自定义类加载器对字节码进行解密还原 双亲委派模型 应用程序是由三种类加载器相互配合从而实现类加载除此之外还可以加入自己定义的类加载器 类加载器之间的层级关系称之为双亲委派模型。该模型要求除了顶层的启动类加载器外其他的类加载器都要有自己的父类加载器这里的父子关系一般通过组合关系来实现而不是继承关系 双亲委派工作机制 一个类加载器首先将类加载请求转发到父类加载器只有当父类加载器无法完成时才尝试自己加载 双亲委派的作用 每个类只会加载一次解决了各个类加载器加载基础类的统一问题(基础类库由上层的加载器进行加载防止恶意破坏的类加载内存中不会出现多份同样的字节码的系统类保证Java程序安全稳定运行 例如java.lang.Object存放在 rt.jar 中如果编写另外一个java.lang.Object 并放到ClassPath 中程序可以编译通过。由于双亲委派模型的存在所以在 rt.jar 中的 Object 比在ClassPath 中的 Obiect 优先级更高因为 rt.jar 中的 Object 使用的是启动类加载器而 ClassPath 中的 Object 使用的是应用程序类加载器。 rt.jar 中的 object 优先级更高那么程序中使用的所有的Object都是由启动类加载器所加载的Object。 双亲委派的实现源码 ​ 以下是抽象类java.lang.ClassLoadr的代码片段其中的loadClass()方法允许过程如下先检查是否已经加载过如果没有则让父类加载器去加载。当父类加载器加载失败时抛出ClassNotFoundException此时尝试自己去加载 SPI打破双亲委派 SPI是一种服务发现机制它通过ClassPath路径下的META-INF/services文件夹查找文件自动加载文件里所定义的类 如下图SPI核心类定义在rt.jar中例如java.lang.Driver接口所以java.lang.Driver接口本身是由启动类加载器加载调用java.lang.Driver接口的实现时启动类加载器无法加载实现类这个时候就提供了线程上下文类加载器(Thread Context ClassLoader)加载实现类ThreadContextClassLoader是可以通过java.lang.Thread#setContextClassLoader方法设置类加载器这样就打破了双亲委派的类加载模式 对象的创建过程 Step1类加载检查 虚拟机遇到一条 new 指令时首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有那必须先执行相应的类加载过程 Step2分配内存 在类加载检查通过后接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。内存分配的查找方式有“指针碰撞”和“空闲列表” 两种 选择以上两种方式中的哪一种取决于Java堆内存是否规整而Java堆内存是否规整取决于GC收集器的算法是‘标记-清楚’还是‘标记-整理’ Step3初始化零值 内存分配完成后虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用程序能访问到这些字段的数据类型所对应的零值。 Step4设置对象头 初始化零值完成之后虚拟机要对对象进行必要的设置例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。另外根据虚拟机当前运行状态的不同如是否启用偏向锁等对象头会有不同的设置方式。 Step5执行init构造方法 在上面工作都完成之后从虚拟机的视角来看一个新的对象已经产生了但从 Java 程序的视角来看对象创建才刚开始init 构造方法还没有执行目前所有的字段都还为零。所以一般来说执行 new 指令之后会接着执行 int 构造方法把对象按照程序逻辑的意愿进行初始化这样一个真正可用的对象才算完整创建出来
http://www.yutouwan.com/news/252427/

相关文章:

  • 建设企业网站官网u盾wordpress .htaccess 规则
  • 自己的主机做服务器网站如何备案网站备案网站建设方案书
  • 专业制作网站服务公司seo排名课程咨询电话
  • 网站权限最专业的网站建设价格
  • 河北省建设工程网站定制微信小程序多少钱
  • 建站专业定制郴州招聘网直招最新招聘
  • 网贷网站开发网站备案号大全
  • 深圳网站设计哪家公司好企业建设网站的目的( )
  • vps建设网站怎么优化网站关键词
  • 网站建设需要学多久企业企业网站建设
  • 静态网页做的网站怎么发到网上怎么做简单的视频网站
  • 建设大型网站需要什么硬件Wordpress哪些出现403
  • 西安公司企业网站建设wordpress 网页计算器
  • 网站翻译建设上海最新发布
  • 高端的网站建设公司zencart官方网站
  • 建设工程竣工规划局网站秦皇岛建设局
  • 官方网站下载抖音连云港seo优化
  • 微网站建设报价方案模板下载网站建设中网站需求分析
  • 樊城网站建设做一个主题wordpress
  • 网站开发现在怎么样网站做pc
  • 安亭网站建设整人做我女朋友网站
  • 小红书网站建设目的wordpress国内訪問
  • 有偷菜餐厅城市建设的网站网站地图模板下载
  • 购物网站开发项目意义上海公共招聘网首页
  • 长沙公司建设网站网站设计机构
  • 网站推广有什么方法深圳市宝安区住房和建设局网站
  • 黄山建设网站公司电话井陉建设局网站公示
  • 企业网站框架图wordpress主题 手机端
  • 做喷绘的图在哪个网站找洛阳高新区做网站公司
  • 网站开发技术html哪个网站做摄影师好