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

怎么做推广和宣传企业做网站wordpress 刷评论数量

怎么做推广和宣传企业做网站,wordpress 刷评论数量,开发app平台需要多少钱,调用别人网站的数据库转载自 【深入Java虚拟机】之四#xff1a;类加载机制 类加载过程 类从被加载到虚拟机内存中开始#xff0c;到卸载出内存为止#xff0c;它的整个生命周期包括#xff1a;加载、验证、准备、解析、初始化、使用和卸载七个阶段。它们开始的顺序如下图所示#xff1a; 其中…转载自 【深入Java虚拟机】之四类加载机制 类加载过程 类从被加载到虚拟机内存中开始到卸载出内存为止它的整个生命周期包括加载、验证、准备、解析、初始化、使用和卸载七个阶段。它们开始的顺序如下图所示 其中类加载的过程包括了加载、验证、准备、解析、初始化五个阶段。在这五个阶段中加载、验证、准备和初始化这四个阶段发生的顺序是确定的而解析阶段则不一定它在某些情况下可以在初始化阶段之后开始这是为了支持Java语言的运行时绑定也成为动态绑定或晚期绑定。另外注意这里的几个阶段是按顺序开始而不是按顺序进行或完成因为这些阶段通常都是互相交叉地混合进行的通常在一个阶段执行的过程中调用或激活另一个阶段。 这里简要说明下Java中的绑定绑定指的是把一个方法的调用与方法所在的类(方法主体)关联起来对java来说绑定分为静态绑定和动态绑定 静态绑定即前期绑定。在程序执行前方法已经被绑定此时由编译器或其它连接程序实现。针对java简单的可以理解为程序编译期的绑定。java当中的方法只有finalstaticprivate和构造方法是前期绑定的。动态绑定即晚期绑定也叫运行时绑定。在运行时根据具体对象的类型进行绑定。在java中几乎所有的方法都是后期绑定的。下面详细讲述类加载过程中每个阶段所做的工作。 加载 加载时类加载过程的第一个阶段在加载阶段虚拟机需要完成以下三件事情 1、通过一个类的全限定名来获取其定义的二进制字节流。 2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。 3、在Java堆中生成一个代表这个类的java.lang.Class对象作为对方法区中这些数据的访问入口。 注意这里第1条中的二进制字节流并不只是单纯地从Class文件中获取比如它还可以从Jar包中获取、从网络中获取最典型的应用便是Applet、由其他文件生成JSP应用等。 相对于类加载的其他阶段而言加载阶段准确地说是加载阶段获取类的二进制字节流的动作是可控性最强的阶段因为开发人员既可以使用系统提供的类加载器来完成加载也可以自定义自己的类加载器来完成加载。 加载阶段完成后虚拟机外部的 二进制字节流就按照虚拟机所需的格式存储在方法区之中而且在Java堆中也创建一个java.lang.Class类的对象这样便可以通过该对象访问方法区中的这些数据。 说到加载不得不提到类加载器下面就具体讲述下类加载器。 类加载器虽然只用于实现类的加载动作但它在Java程序中起到的作用却远远不限于类的加载阶段。对于任意一个类都需要由它的类加载器和这个类本身一同确定其在就Java虚拟机中的唯一性也就是说即使两个类来源于同一个Class文件只要加载它们的类加载器不同那这两个类就必定不相等。这里的“相等”包括了代表类的Class对象的equals、isAssignableFrom、isInstance等方法的返回结果也包括了使用instanceof关键字对对象所属关系的判定结果。 站在Java虚拟机的角度来讲只存在两种不同的类加载器 启动类加载器它使用C实现这里仅限于Hotspot也就是JDK1.5之后默认的虚拟机有很多其他的虚拟机是用Java语言实现的是虚拟机自身的一部分。所有其他的类加载器这些类加载器都由Java语言实现独立于虚拟机之外并且全部继承自抽象类java.lang.ClassLoader这些类加载器需要由启动类加载器加载到内存中之后才能去加载其他的类。站在Java开发人员的角度来看类加载器可以大致划分为以下三类 启动类加载器Bootstrap ClassLoader跟上面相同。它负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录下同)下或被-Xbootclasspath参数指定的路径中的并且能被虚拟机识别的类库如rt.jar所有的java.*开头的类均被Bootstrap ClassLoader加载。启动类加载器是无法被Java程序直接引用的。扩展类加载器Extension ClassLoader该加载器由sun.misc.Launcher$ExtClassLoader实现它负责加载JDK\jre\lib\ext目录中或者由java.ext.dirs系统变量指定的路径中的所有类库如javax.*开头的类开发者可以直接使用扩展类加载器。应用程序类加载器Application ClassLoader该类加载器由sun.misc.Launcher$AppClassLoader来实现它负责加载用户类路径ClassPath所指定的类开发者可以直接使用该类加载器如果应用程序中没有自定义过自己的类加载器一般情况下这个就是程序中默认的类加载器。应用程序都是由这三种类加载器互相配合进行加载的如果有必要我们还可以加入自定义的类加载器。因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件因此如果编写了自己的ClassLoader便可以做到如下几点 1在执行非置信代码之前自动验证数字签名。 2动态地创建符合用户特定需要的定制化构建类。 3从特定的场所取得java class例如数据库中和网络中。 事实上当使用Applet的时候就用到了特定的ClassLoader因为这时需要从网络上加载java class并且要检查相关的安全信息应用服务器也大都使用了自定义的ClassLoader技术。 这几种类加载器的层次关系如下图所示 这种层次关系称为类加载器的双亲委派模型。我们把每一层上面的类加载器叫做当前层类加载器的父加载器当然它们之间的父子关系并不是通过继承关系来实现的而是使用组合关系来复用父加载器中的代码。该模型在JDK1.2期间被引入并广泛应用于之后几乎所有的Java程序中但它并不是一个强制性的约束模型而是Java设计者们推荐给开发者的一种类的加载器实现方式。 双亲委派模型的工作流程是如果一个类加载器收到了类加载的请求它首先不会自己去尝试加载这个类而是把请求委托给父加载器去完成依次向上因此所有的类加载请求最终都应该被传递到顶层的启动类加载器中只有当父加载器在它的搜索范围中没有找到所需的类时即无法完成该加载子加载器才会尝试自己去加载该类。 使用双亲委派模型来组织类加载器之间的关系有一个很明显的好处就是Java类随着它的类加载器说白了就是它所在的目录一起具备了一种带有优先级的层次关系这对于保证Java程序的稳定运作很重要。例如类java.lang.Object类存放在JDK\jre\lib下的rt.jar之中因此无论是哪个类加载器要加载此类最终都会委派给启动类加载器进行加载这边保证了Object类在程序中的各种类加载器中都是同一个类。 验证 验证的目的是为了确保Class文件中的字节流包含的信息符合当前虚拟机的要求而且不会危害虚拟机自身的安全。不同的虚拟机对类验证的实现可能会有所不同但大致都会完成以下四个阶段的验证文件格式的验证、元数据的验证、字节码验证和符号引用验证。 文件格式的验证验证字节流是否符合Class文件格式的规范并且能被当前版本的虚拟机处理该验证的主要目的是保证输入的字节流能正确地解析并存储于方法区之内。经过该阶段的验证后字节流才会进入内存的方法区中进行存储后面的三个验证都是基于方法区的存储结构进行的。元数据验证对类的元数据信息进行语义校验其实就是对类中的各数据类型进行语法校验保证不存在不符合Java语法规范的元数据信息。字节码验证该阶段验证的主要工作是进行数据流和控制流分析对类的方法体进行校验分析以保证被校验的类的方法在运行时不会做出危害虚拟机安全的行为。符号引用验证这是最后一个阶段的验证它发生在虚拟机将符号引用转化为直接引用的时候解析阶段中发生该转化后面会有讲解主要是对类自身以外的信息常量池中的各种符号引用进行匹配性的校验。准备 准备阶段是正式为类变量分配内存并设置类变量初始值的阶段这些内存都将在方法区中分配。对于该阶段有以下几点需要注意 1、这时候进行内存分配的仅包括类变量static而不包括实例变量实例变量会在对象实例化时随着对象一块分配在Java堆中。 2、这里所设置的初始值通常情况下是数据类型默认的零值如0、0L、null、false等而不是被在Java代码中被显式地赋予的值。 假设一个类变量的定义为 public static int value 3 那么变量value在准备阶段过后的初始值为0而不是3因为这时候尚未开始执行任何Java方法而把value赋值为3的putstatic指令是在程序编译后存放于类构造器clinit方法之中的所以把value赋值为3的动作将在初始化阶段才会执行。 下表列出了Java中所有基本数据类型以及reference类型的默认零值 这里还需要注意如下几点 对基本数据类型来说对于类变量static和全局变量如果不显式地对其赋值而直接使用则系统会为其赋予默认的零值而对于局部变量来说在使用前必须显式地为其赋值否则编译时不通过。对于同时被static和final修饰的常量必须在声明的时候就为其显式地赋值否则编译时不通过而只被final修饰的常量则既可以在声明时显式地为其赋值也可以在类初始化时显式地为其赋值总之在使用前必须为其显式地赋值系统不会为其赋予默认零值。对于引用数据类型reference来说如数组引用、对象引用等如果没有对其进行显式地赋值而直接使用系统都会为其赋予默认的零值即null。如果在数组初始化时没有对数组中的各元素赋值那么其中的元素将根据对应的数据类型而被赋予默认的零值。3、如果类字段的字段属性表中存在ConstantValue属性即同时被final和static修饰那么在准备阶段变量value就会被初始化为ConstValue属性所指定的值。 假设上面的类变量value被定义为  public static final int value 3 编译时Javac将会为value生成ConstantValue属性在准备阶段虚拟机就会根据ConstantValue的设置将value赋值为3。回忆上一篇博文中对象被动引用的第2个例子便是这种情况。我们可以理解为static final常量在编译期就将其结果放入了调用它的类的常量池中。 解析 解析阶段是虚拟机将常量池中的符号引用转化为直接引用的过程。在Class类文件结构一文中已经比较过了符号引用和直接引用的区别和关联这里不再赘述。前面说解析阶段可能开始于初始化之前也可能在初始化之后开始虚拟机会根据需要来判断到底是在类被加载器加载时就对常量池中的符号引用进行解析初始化之前还是等到一个符号引用将要被使用前才去解析它初始化之后。 对同一个符号引用进行多次解析请求时很常见的事情虚拟机实现可能会对第一次解析的结果进行缓存在运行时常量池中记录直接引用并把常量标示为已解析状态从而避免解析动作重复进行。 解析动作主要针对类或接口、字段、类方法、接口方法四类符号引用进行分别对应于常量池中的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info四种常量类型。 1、类或接口的解析判断所要转化成的直接引用是对数组类型还是普通的对象类型的引用从而进行不同的解析。 2、字段解析对字段进行解析时会先在本类中查找是否包含有简单名称和字段描述符都与目标相匹配的字段如果有则查找结束如果没有则会按照继承关系从上往下递归搜索该类所实现的各个接口和它们的父接口还没有则按照继承关系从上往下递归搜索其父类直至查找结束查找流程如下图所示 从下面一段代码的执行结果中很容易看出来字段解析的搜索顺序 class Super{ public static int m 11; static{ System.out.println(执行了super类静态语句块); } } class Father extends Super{ public static int m 33; static{ System.out.println(执行了父类静态语句块); } } class Child extends Father{ static{ System.out.println(执行了子类静态语句块); } } public class StaticTest{ public static void main(String[] args){ System.out.println(Child.m); } } 执行结果如下 执行了super类静态语句块     执行了父类静态语句块     33     如果注释掉Father类中对m定义的那一行则输出结果如下 执行了super类静态语句块     11 另外很明显这就是上篇博文中的第1个例子的情况这里我们便可以分析如下static变量发生在静态解析阶段也即是初始化之前此时已经将字段的符号引用转化为了内存引用也便将它与对应的类关联在了一起由于在子类中没有查找到与m相匹配的字段那么m便不会与子类关联在一起因此并不会触发子类的初始化。 最后需要注意理论上是按照上述顺序进行搜索解析但在实际应用中虚拟机的编译器实现可能要比上述规范要求的更严格一些。如果有一个同名字段同时出现在该类的接口和父类中或同时在自己或父类的接口中出现编译器可能会拒绝编译。如果对上面的代码做些修改将Super改为接口并将Child类继承Father类且实现Super接口那么在编译时会报出如下错误 StaticTest.java:24: 对 m 的引用不明确Father 中的 变量 m 和 Super 中的 变量 m 都匹配                 System.out.println(Child.m);                                         ^ 1 错误 3、类方法解析对类方法的解析与对字段解析的搜索步骤差不多只是多了判断该方法所处的是类还是接口的步骤而且对类方法的匹配搜索是先搜索父类再搜索接口。 4、接口方法解析与类方法解析步骤类似知识接口不会有父类因此只递归向上搜索父接口就行了。 初始化 初始化是类加载过程的最后一步到了此阶段才真正开始执行类中定义的Java程序代码。在准备阶段类变量已经被赋过一次系统要求的初始值而在初始化阶段则是根据程序员通过程序指定的主观计划去初始化类变量和其他资源或者可以从另一个角度来表达初始化阶段是执行类构造器clinit()方法的过程。 这里简单说明下clinit方法的执行规则: 1、clinit方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的编译器收集的顺序是由语句在源文件中出现的顺序所决定的静态语句块中只能访问到定义在静态语句块之前的变量定义在它之后的变量在前面的静态语句中可以赋值但是不能访问。 2、clinit方法与实例构造器init方法类的构造函数不同它不需要显式地调用父类构造器虚拟机会保证在子类的clinit方法执行之前父类的clinit方法已经执行完毕。因此在虚拟机中第一个被执行的clinit方法的类肯定是java.lang.Object。 3、clinit方法对于类或接口来说并不是必须的如果一个类中没有静态语句块也没有对类变量的赋值操作那么编译器可以不为这个类生成clinit方法。 4、接口中不能使用静态语句块但仍然有类变量final static初始化的赋值操作因此接口与类一样会生成clinit方法。但是接口鱼类不同的是执行接口的clinit方法不需要先执行父接口的clinit方法只有当父接口中定义的变量被使用时父接口才会被初始化。另外接口的实现类在初始化时也一样不会执行接口的clinit方法。 5、虚拟机会保证一个类的clinit方法在多线程环境中被正确地加锁和同步如果多个线程同时去初始化一个类那么只会有一个线程去执行这个类的clinit方法其他线程都需要阻塞等待直到活动线程执行clinit方法完毕。如果在一个类的clinit方法中有耗时很长的操作那就可能造成多个线程阻塞在实际应用中这种阻塞往往是很隐蔽的。 下面给出一个简单的例子以便更清晰地说明如上规则 class Father{ public static int a 1; static{ a 2; } } class Child extends Father{ public static int b a; } public class ClinitTest{ public static void main(String[] args){ System.out.println(Child.b); } } 执行上面的代码会打印出2也就是说b的值被赋为了2。 我们来看得到该结果的步骤。首先在准备阶段为类变量分配内存并设置类变量初始值这样A和B均被赋值为默认值0而后再在调用clinit方法时给他们赋予程序中指定的值。当我们调用Child.b时触发Child的clinit方法根据规则2在此之前要先执行完其父类Father的clinit方法又根据规则1在执行clinit方法时需要按static语句或static变量赋值操作等在代码中出现的顺序来执行相关的static语句因此当触发执行Father的clinit方法时会先将a赋值为1再执行static语句块中语句将a赋值为2而后再执行Child类的clinit方法这样便会将b的赋值为2. 如果我们颠倒一下Father类中“public static int a 1;”语句和“static语句块”的顺序程序执行后则会打印出1。很明显是根据规则1执行Father的clinit方法时根据顺序先执行了static语句块中的内容后执行了“public static int a 1;”语句。 另外在颠倒二者的顺序之后如果在static语句块中对a进行访问比如将a赋给某个变量在编译时将会报错因为根据规则1它只能对a进行赋值而不能访问。   总结 整个类加载过程中除了在加载阶段用户应用程序可以自定义类加载器参与之外其余所有的动作完全由虚拟机主导和控制。到了初始化才开始执行类中定义的Java程序代码亦及字节码但这里的执行代码只是个开端它仅限于clinit方法。类加载过程中主要是将Class文件准确地讲应该是类的二进制字节流加载到虚拟机内存中真正执行字节码的操作在加载完成后才真正开始。
http://www.yutouwan.com/news/29619/

相关文章:

  • html怎么做移动端网站东莞网站推广策划活动
  • jsp电影网站开发教程站酷网站
  • 去哪儿网站建设需要哪些技术淮南做网站公司
  • 个人域名做邮箱网站建设平台网站
  • 设计网站公司好评y湖南岚鸿ok免备案做网站 可以盈利吗
  • 企业建设网站费用中国设计者联盟官网
  • 东莞模板网站好临安做网站的公司
  • 山东城市建设职业学院教务网站做的好的电商网站项目
  • 朔州seo网站建设株洲有实力关键词优化服务
  • 长春专业做网站的公司排名精准客户资源购买
  • 做公司官方网站手把手做网站
  • 行业网站制作怎么形容网站做的好
  • 便宜电商网站建设怎么样才能做好营销
  • 厚街网站建设费用黔西南州做网站
  • 中国建设银行信用卡网站关键词排名零芯互联关键词
  • 云南建设厅网站资质查询网站上传百度多久收录
  • 做php网站前端代码高亮网站
  • 广州网站优化指导旅游网站建设怎么做
  • 网站没备案能百度推广吗做一个个人网站多少钱
  • 网站建站多少钱手机怎做网站
  • 千博网站后台网页设计构建的基本流程
  • 网站建设第一品牌 网站设计如何做好seo基础优化
  • 用jsp做网站的难点百度指数查询官网入口登录
  • 福州招聘网站有哪几个哈尔滨建设发展集团
  • 中冶东北建设最新网站濮阳建设公司网站
  • 游戏评测网站怎么做哪些网站才能具备完整的八项网络营销功能
  • 一个做音乐的网站2020做seo还有出路吗
  • 网站建设海报设计长沙地区网络优化设计方案
  • 皖icp合肥网站建设岳阳卖房网站
  • 甘肃省城乡建设局网站首页安阳县陈佳