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

wordpress企业站实例wordpress文档id初始化

wordpress企业站实例,wordpress文档id初始化,专业舆情公关公司,许昌做网站的公司字节码的结构 魔数u4 cafe babe 版本u4 52 java8 常量池计数器u2 从1开始#xff0c;0索引留给不需要的情况 常量池 表 #1 - #计数器-1 类标识符 u2 public final abstrat class annotion interface 之类 类索引u2 名字 父类索引u2 父类名字 接口计数器 u2 接口数…字节码的结构 魔数u4 cafe babe 版本u4 52 java8 常量池计数器u2 从1开始0索引留给不需要的情况 常量池 表 #1 - #计数器-1 类标识符 u2 public final abstrat class annotion interface 之类 类索引u2 名字 父类索引u2 父类名字 接口计数器 u2 接口数组长度 接口集合 表 接口索引数组 字段计数器 u2 字段 表 -访问标识符 u2 -字段名索引 u2 -字段描述符索引 u2 -字段属性计数器 u2 -字段属性 表 方法计数器 u2 方法 表 -访问标识符 u2 -方法名索引 u2 -方法描述符索引 u2 -方法属性计数器 u2 -方法属性 表 前段编译器 将高级语言源文件编译成Class文件的过程就是前端编译的过程。这是java跨平台执行的关键。 前段编译器只负责将高级语言编译成字节码不负责具体的性能优化之类的这些要在执行引擎中的JIT及时编译器中负责。 前段编译器编译的流程如下。 词法分析 检查关键字引用等等有没有错误。 语法分析 根据具体的高级语言的语法分析是否出现语法错误。 语义分析 根据逻辑关系分析是否有可能出现的逻辑问题。比如未初始化啊数组越界之类的。这部分的功能有限只能发现较为明显的逻辑错误。 生成字节码 类加载过程 字节码文件并不存放在内存中而是在内存外可能是在磁盘中也可能在网络中也可能是动态生成的。当需要用到的时候再由类加载去寻找并载入内存到运行时数据区才可以被JVM使用。 类加载的过程有7个阶段。 加载——验证——准备——解析——初始化——使用——卸载 加载 1 通过某种方式找到对应的Class文件获取到二进制数据流。 2 解析二进制数据流并根据来建立对应方法区中的数据结构。 3 创建java.lang.Class类对象实例用来作为方法区访问类数据的入口。也就是给一个索引到方法区数据结构的对象 Class类的构造方法是私有的只有JVM可以创建。然后这个Class实例对象是元空间的入口也是实现反射的关键数据。通过Class类提供的接口方法可以获得这个描述类的种种信息。 验证 属于链接中的第一步。 加载到内存之后我们就可以快速的对字节码进行验证保证字节码是合法合规合理的。 字节码格式验证字节码语义验证字节码验证逻辑符号引用验证。 这和前端编译器编译流程很像词法分析对应格式验证语法分析对应语义验证语义分析对应字节码验证以及符号引用验证。 准备阶段 这个时候字节码通过验证了那么可以开始完善类的静态部分了这样一个Class对象算是可用。 也就是静态的成员变量分配内存初始化值。 1 分配内存并进行初始化内存。 对于类的静态成员变量都会先对内存空间初始化一个值根据类型不同初始化的也不同。 java不支持boolean原生类型内部实现实际上是通过int实现。默认int 0对应false。 这个初始化默认值对于static final修饰的基本数据类型无用所以没有因为其不需要多这么个初始为默认值的步骤而可以直接确定最终值在准备阶段直接进行显式赋值。另外对于String类型在显式赋值中不涉及方法或构造器调用其初始化是在链接阶段的准备环节进行 对于实例变量在准备阶段不会进行初始化因为实例变量会随着实例对象分配到堆中你不能提前知道要创建实例对象了并提前给创建好。 仅仅是初始化内存空间相当于清理垃圾并不会执行任何代码来赋值这一步是后面初始化阶段做的事情 解析阶段 将符号引用转换为实际的直接引用。在实际的运行环境中寻找符号引用的直接引用替换到类对象中。 这个阶段有可能在初始化之后再进行不确定。 初始化阶段 这是类装载的最后一个阶段。这个阶段JVM才会执行初始化代码根据类的初始化代码进行初始化类对象。 最重要的工作就是执行cinit方法。类的初始化方法这个方法只能由java编译器生成并只能被JVM调用我们无法调用。 cinit()是根据类的静态成员赋值语句以及static代码块合并形成的。但是需要记住在加载子类之前JVM总会试图先加载其父类所以父类的《cinit》一定先于子类的《cinit》执行。 如果没有静态赋值语句和静态代码块那么编译器就不会产生《cinit》方法 cinit方法只能在类加载的时候被调用一次后续不能再调用所以当JVM内部多个线程同时加载一个类的时候就需要保证线程安全cinit方法自带同步锁只有一个线程能执行cinit其他线程都阻塞。等待执行完毕后会通知其他线程返回这个结果。 如果cinit中出现耗时长操作会导致线程阻塞难以排查。 初始化时机cinit调用时机 因为要执行代码所以无疑初始化需要时间开销。所以并不是任何时候都能随时进行初始化的。初始化的时机就变得非常重要。 有两种使用类的方式主动使用会导致初始化发生被动使用不需要初始化。 1 主动使用核心就是涉及用到Class对象 也就是当我们需要用到类的静态变量了那么一定会进行初始化。 new实例对象或者反序列化得到实例对象 反射获取到Class对象 调用静态方法静态方法可能涉及到静态变量的访问所以可能静态成员变量需要初始化。 访问未被初始化阶段赋值的静态成员变量如果访问static final修饰的在准备阶段就赋值的静态变量那不需要初始化就可以但是是static final String NAME new String”123:“这种就不可以 对于接口来说所有的静态字段都是static final修饰的效果和类一样。 初始化子类时如果发现其父类还没有进行过初始化则需要先触发其父类的初始化。JVM虚拟机初始化一个类时要求它的所有父类都已经被初始化但是这条规则并不适用于接口。在初始化一个类时并不会先初始化它所实现的接口在初始化一个接口时并不会先初始化它的父接口。因此一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态字段时才会导致该接口的初始化 如果一个接口定义了default方法那么直接实现或者间接实现该接口的类在初始化之前需要实现接口的初始化 JVM启动时用户需要指定一个要执行的主类包含main()方法的那个类,JVM会先初始化这个主类。这个类在调用main()方法之前被链接和初始化main()方法的执行将依次加载链接和初始化后面需要使用到的类。 初次创建MethodHandle实例时初始化该MethodHandle实例时指向的方法所在的类 2 被动使用 并不是在代码中出现的类就一定会被加载或者初始化 当访问一个静态字段时只有真正声明这个字段的类才会被初始化。当通过子类引用父类的静态变量不会导致子类初始化而如果访问子类的就会导致父类进行初始化以及子类的初始化 通过数组定义类引用不会触发此类的初始化。直到给具体的数组中的元素赋予对象才会。数组定义的引用只是从编译阶段确定所以并不会导致初始化。 引用常量不会触发此类或接口的初始化因为常量在链接阶段已经被显式赋值 调用ClassLoader类的loadClass()方法加载一个类并不是对类的主动使用不会导致类的初始化。通过反射获取到Class对象才会导致初始化例如Class.forName()会导致初始化。 类的卸载 类的卸载涉及到类加载类Class对象类实例之间的引用关系。 类加载器和加载的类对象相互关联。类加载内部Java集合存放了加载过的类对象引用而类对象也引用加载他的类加载器。 类实例总是引用代表这个类的Class对象getClass类中都有一个静态属性class通过类名.class可获得引用着这个类的Class对象。 所以条条大路通Class对象。 所以什么时候卸载类要等到Class对象不在被引用的时候。 所以类被卸载的三个条件都是围绕Class对象被引用 所有类的实例对象都被回收 Class对象没有直接被引用 类的加载器被GC回收只有用户自定义加载器能够被回收 这样图中Order.class实例的三个方向的引用都断了那么可以卸载类了。 类加载器 实际上属于类加载过程的细节。类加载过程中第一个加载阶段就是类加载器负责的。 类加载器在整个装载阶段只能影响到类的加载而无法改变类的链接和初始化行为存疑 类加载器必要性 了解类加载器机制可以解决以下问题。 (1)避免在开发中遇到java.lang.ClassNotFoundException异常或java.lang.NoClassDefFoundError异常时手足无措。 (2)只有了解类加载器的加载机制才能够在出现异常的时候快速地根据错误异常日志定位并解决问题。 (3)需要支持类的动态加载或需要对编译后的class文件进行加解密操作时就需要与类加载器打交道。 (4)开发人员可以在程序中编写自定义类加载器来重新定义类的加载规则以便实现一些自定义的处理逻辑 也就是异常处理动态或者自定义加载 类加载器的命名空间 每一个类是通过加载它的类加载器加上类本身的名字来确定其在JVM中的唯一性而不仅仅是通过类的名字。 每个类加载器都有自己的命名空间命名空间由该类加载器实例及所有的父类加载器组成在同一命名空间中不会出现类的完整名字包括类的包名相同的两个类 这样就保证了类的唯一性。 在不同的命名空间中有可能会出现类的完整名字包括类的包名相同的两个类在大型应用中我们往往借助这一特性来运行同一个类的不同版本。 也就是通过不同的类加载器加载一个类的不同版本。 类加载的基本特征 通常有三大特征双亲委派可见性单一性 双亲委派实际上就是优先交给上一级加载器加载。这样是为了避免类在其他地方重复加载第二个是恶意代码不能通过重复加载来替换核心类库。 可见性是下级加载器可以访问上级加载器加载了哪些类型反过来是不行的。也就是说高级加载器加载的类只能看到自己和更高级的类的存在如果和同级或者下级类进行交互是ClassNotFound的。而下级加载器加载的类就可以看到上级加载器加载的类的存在。就像是父类和子类的关系一样但是只能是访问关系一样 单一性因为父加载器加载过的类型对于子加载器是可见的所以父加载器加载的类型就不会在子加载器中重复加载。但是在同一级的加载器中兄弟加载器相互是不可见的所以同一个类可以被同级别的加载器加载多次。 类加载器的分类 实际上就是类加载器分级是根据什么分级的不同级别的类加载器有什么职责。 从最本质的来分JVM有两种类加载器启动类加载器和自定义类加载器。 自定义类加载器通常是指由开发人员自定义的一类类加载器但是Java虚拟机规范中规定的更为广泛凡是从抽象类ClassLoader派生而来的类加载器都是自定义类加载器。那么不是从ClassLoader派生而来的类加载器自然就是启动类加载器了。 无论类加载器的类型如何划分在程序中我们最常见的类加载器结构如图20-1所示其中扩展类加载器和应用程序类由抽象类ClassLoader派生而来 实际上不同加载器之间是聚合关系也就是下级加载器有上级加载器的引用。而不是继承关系。 只是在ClassLoader这个抽象类中有一个成员变量引用上一级的加载器叫做parent。所以上级加载器才被叫做父加载器。 引导类加载器启动类加载器 这两种称呼一种是基于职责负责引导程序运行一种是指是启动程序的类加载器。 引导类加载器BootstrapClassLoader又称启动类加载器使用C/C语言实现嵌套在JVM内部。 引导类加载器不继承java.lang.ClassLoader没有父类加载器。出于安全考虑引导类加载器主要用来加载Java的核心库也就是“JAVA_HOME/jre/lib/rt.jar”或“sun.boot.class.path”路径下的内容指定为扩展类和应用程序类加载器的父类加载器。 所以引导类加载器作用有限主要用来加载核心类库。 扩展类加载器 扩展类加载器(ExtensionClassLoader)由Java语言编写间接继承与ClassLoader 扩展类加载器主要负责从java.ext.dirs系统属性所指定的目录或者JDK的安装目录的jre/lib/ext子目录下加载类库。如果用户创建的类放在上述目录下也会自动由扩展类加载器加载。简言之扩展类加载器主要负责加载Java的扩展库。 应用程序类加载器 也叫做系统加载器也是由Java语言编写间接继承于ClassLoader类父类加载器为扩展类加载器。 负责加载环境变量classpath或系统属性java.class.path指定路径下的类库应用程序中的类加载器默认是应用程序类加载器。在IDE中可以查看到JDK的CLASSPATH。在命令行执行的时候CLASSPATH就是当前路径 它是用户自定义类加载器的默认父类加载器通过ClassLoader的getSystemClassLoader()方法可以获取到该类加载器。 自定义加载器 自定义加载器有很多好处。 实现插件效果即插即用。通过启用自定义加载器加载额外功能。不需要的时候直接回收自定义加载器就拔除功能。 隔离加载类。同级类加载器之间相互隔离。所以我们可以通过将不同的类簇通过不同的同级类加载器加载实现隔离。 修改类加载方式除了启动类加载器之外其他的类加载器并非一定引入。所以我们可以改变类加载器的加载。 扩展加载源。如果需要加载从咔咔郭郭来的类可以通过自定义加载器载入。 提高程序的安全性。在一般情况下使用不同的类加载器去加载不同的功能模块会提高应用程序的安全性。但是如果涉及Java类型转换则加载器反而容易产生不美好的事情。在做Java类型转换时只有两个类型都是由同一个加载器所加载才能进行类型转换否则转换时会发生异常。 获取常见类的加载器 方式加载器类型class对象.getClassLoader()获取class对象的类加载器Thread.currentThread().getContextClassLoader()当前线程上下文的类加载器ClassLoader.getSystemClassLoader()获取系统类加载器classLoader对象.getParent()获取父类加载器 这些加载器大多都是由应用类加载器来充当。 可以看到都是应用类加载器加载的。 引导类加载器结果为null原因是引导类加载器是C语言编写并不是一个java对象所以这里用null展示。 数组类特殊 数组类的Class对象不是由类加载器创建的而是在Java运行期JVM根据需要自动创建的。数组类的类加载器可以通过Class.getClassLoader()方法返回如果数组元素是引用数据类型类加载器与数组当中元素类型相同如果数组元素类型是基本数据类型就没有类加载器 System.out.println(int[][].class.getClassLoader());//输出nullSystem.out.println(ClassLoaderTest[][].class.getClassLoader());//输出sun.misc.Launcher$AppClassLoader18b4aac2 源码分析 有必要学习类加载器的源码。 ClassLoader主要方法 抽象类ClassLoader的主要方法内部没有抽象方法如下。 1)public final ClassLoader getParent()该方法作用是返回该类加载器的父类加载器。 2)public Class?loadClass(String name)throws ClassNotFoundException该方法作用是加载名称为name的类返回结果为java.lang.Class类的实例。如果找不到类则抛出“ClassNotFoundException”异常。 该方法中的逻辑就是双亲委派模型的实现 具体操作就是 sychronized保证同步没问题 查看自己是否加载过 通过findLoadedClass ,也就是protected final Class?findLoadedClass(String name) ) 调用父加载器进行加载如果父为空调用findBootstrapClassOrNull加载 父加载器失败自己加载 通过findClass(name) 进行链接操作 resolveClass (也就是 验证,准备,解析 这三个操作) 这里的findClass方法就很重要了最为加载器的兜底逻辑负责查找二进制名为name的类返回的是Class类实例。 protected Class?findClass(String name)throws ClassNotFoundException 在jdk1.2之后官方已经不建议我们重写loadClass方法因为loadClass方法中实现保证了双亲委派机制的逻辑。我们自己的逻辑建议写在findClass方法中。当loadClass()方法中父类加载器加载失败后则会调用自己的findClass()方法来完成类加载这样就可以保证自定义的类加载器也符合双亲委托模型。 在findClass中应该调用defineClass将找到的二进制流转换成Class对象。 protected final Class?defineClass(String name,byte [] b,int off,int len) 通过这个方法不仅能够通过class文件实例化Class实例对象也可以通过其他方式实例化Class对象如通过网络接收一个类的字节码然后转换为byte字节流创建对应的Class对象 protected final void resolveClass(Class?c) 使用该方法可以使用类的Class对象创建完成的同时也被解析。前面我们说链接阶段主要是对字节码进行验证为类变量分配内存并设置初始值同时将class文件中的符号引用转换为直接引用 也就是 SecureClassLoader与URLClassLoader ClassLoader中有很多方法没有实现。SecureClassLoader新增了对Class源的验证权限之类的方法。 他的子类URLClassLoader给ClassLoader众多没实现的方法提供了实现。例如findClassfindResouce方法。新增了通过URLClassPath类来协助获取Class字节码流的功能。 我们可以通过继承自URLClassLoader来避免实现过于复杂的findClass和字节码获取代码。 ExtClassLoader与AppClassLoader 这两个类加载器都继承自URLClassLoader。是sun.misc.lanucher的内部静态类。sun.misc.lanucher主要用来启动主应用程序。 类加载调用方法 一般通过Class.forName(全限定名)或者classLoader实例.loadClass(全限定名)加载一个类。 不同的是Class方法会在加载到内存同时进行初始化。 而classLoader实例方法只会加载到内存不会触发实例化。 让自定义类加载器加载类的办法 如果在findClass中不做什么改变那么类一般都会让父加载器也就是AppClassLoader给加载了。所以我们需要在loaderClass的时候传入类名而不是全限定名这样父加载器就找不到类会交给自定义加载器加载。在findClass中我们再拼接出类的路径找到类文件然后进行加载。 双亲委派模型的改变 双亲委派机制并不是必须的而是java设计者推荐的一种类加载器实现机制。 他的好处是 避免重复加载 保护程序安全 打破双亲委派机制也无法破坏核心类库的唯一加载 在ClassLoader中的final defineClass方法中为核心类库提供了一层保护机制。无论是什么类加载器最终都会调用defineClass这个方法这个方法final不能重写在其内部调用preDefineClass方法对核心类库进行保护。 他的劣势是 因为我们只设计了父级类加载器的成员变量引用那么我们的类去寻找其他的类的时候只能先获取自己的ClassLoader然后从ClassLoader中获取findLoadedClass找不到只能向上找loadedClass。所以无法访问下级类加载器加载的类。 破坏双亲委派机制的三种 为了兼容性 jdk1.2之前并没有引入双亲委派机制所以自定义类加载器很多都是通过重写loadClass实现的。在引入之后为了兼容这些代码就没有以技术手段防止loadClass被重写。创建了一个prorected findClass来代替重写loadClass。 SPI场景不同的类加载器加载的类之间的交互 简单来说就是接口定义在了启动类加载器中而实现类定义在了其他类加载器中当启动类加载器需要加载其他子类加载器路径中的类时需要使用线程上下文类加载器默认是应用程序类加载器这样以上下文加载器为中介使得启动类加载器中的代码也可以访问应用类加载器中的类。 线程上下文类加载器实际上是一个帽子主要看我们让哪一个类加载器来带上这个帽子。带上什么帽子起什么作用。原来的findLoadedClass是一条只能向上的线通过线程上下文类加载器这样就可以形成一个环。我们通常让APPClassLoader来充当线程上下文类加载器这样AppClassloaderExtratClassLoaderBootstrapClassLoader形成了一个环那么这三个类加载器中加载的类就都相互可查询可见了。 为了热部署 追求程序的动态性代码热部署模块热替换等。 java并不天生支持热替换。热替换是指在程序的运行过程中不停止服务只通过替换程序文件来修改程序的行为。热替换的关键需求在于服务不能中断修改必须立即表现正在运行的系统之中。 如果一个类已经加载到系统中通过修改类文件并无法让系统再来加载并重定义这个类。 但是如果我们就是想要重新加载并定义这个类呢为了不影响程序的运行我们不能卸载这个类但是我们可以通过加载一个同名类来替换。要做到这件事首先我们需要防止触发重复加载我们需要换一个类加载器这样JVM会认为是不同的类然后加载进去不能调用loadClass这样会交由AppClassLoader加载就是会认为加载过了。 复习路线 JVM 复习1-CSDN博客
http://www.lakalapos1.cn/news/77801/

相关文章:

  • 百度站长工具怎么用抚顺网站建设7113
  • 西安建设局官方网站电子商务网站建设与管理读书心得
  • 公众号代运营平台网站模板如何优化
  • d开头的做网站的软件网站服务器建设方法
  • 找人 做网站 一般注意wordpress 博客模版
  • 电子商务网站建设规划教案浙江温州网络公司
  • 在什么网站可以接国外的模具做做网站最专业的公司
  • 自己做商业网站写作平台有哪些
  • 鹤壁网站推广百度最新版本2022
  • 江阴网站推广成都工商注册咨询电话
  • 做彩票网站捉怎么处理网络营销方式案例
  • 仿阿里云网站迁安做网站
  • 网站推广广告大学生实训网站建设心得
  • 怎么诊断网站网站开发综合课程设计
  • 免费发布信息的网站平台有哪些女人和男人做爰网站
  • 岳池做网站电话网站新备案不能访问
  • 手机网站信任从哪里设置wordpress多条件过滤
  • 蚂蚁建站开发手机网站用什么语言
  • 气象服务网站建设网站建设淘宝评价
  • 网站建设遇到的问题及解决方法国家企业信用信息公示系统(官网)
  • 三原网站建设做化工外贸需要那些网站
  • 英语培训网站模板网站推广优化哪家正规
  • 四川建设厅官方网站查询成都高端网站建设那家好
  • 江西省城乡建设厅网站wordpress首次请求慢
  • 蒙牛官网网站怎么做的怎么建立自己公司的网站
  • 佛山网站架设整合网络营销公司
  • 剑网三奇遇查询网站怎么做吴桥县网站建设公司
  • 上海建设工程安全监理网站收银系统软件一套多少钱
  • 广州网站建设程序员培训怎样免费做游戏代理
  • 个人网站模板怎么用阿里云上如何用iis做网站