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

网站seo的推广计划wordpress视频 小程序

网站seo的推广计划,wordpress视频 小程序,常州app制作,wordpress 文章音频前言 我们在学习 java 基础的时候#xff0c;从宏观上了解一个类到运行大致是#xff1a;.java 文件通过 javac 编译器编译得到 .class 文件#xff0c;在用到该类时#xff0c;jvm 会加载该 class 文件#xff0c;并创建对应的 class 对象#xff0c;将 class 文件加载…前言 我们在学习 java 基础的时候从宏观上了解一个类到运行大致是.java 文件通过 javac 编译器编译得到 .class 文件在用到该类时jvm 会加载该 class 文件并创建对应的 class 对象将 class 文件加载到 jvm 的内存当中这个过程也被称之为类加载过程。 下面我们将详细了解这个过程本篇过长建议先收藏。 1、类加载过程 其实关于类加载过程是分为5个阶段的 加载验证准备解析初始化 接下来我们看一下这五个阶段 1.1 加载 JVM 在该阶段的主要目的是将字节码从不同的数据源可能是 class 文件、也可能是 jar 包甚至网络转化为二进制字节流加载到内存中并生成一个代表该类的 java.lang.Class 对象。 1.2 验证 这一阶段的主要目的是为了确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求并且不会危害虚拟机自身的安全只有符合 JVM 字节码规范的才能被 JVM 正确执行。该阶段是保证 JVM 安全的重要屏障下面是一些主要的检查。 确保二进制字节流格式符合预期比如说是否以 cafe bene 咖啡北鼻开头。 是否所有方法都遵守访问控制关键字的限定。 方法调用的参数个数和类型是否正确。 确保变量在使用之前被正确初始化了。 检查变量是否被赋予恰当类型的值。 1.3 准备 JVM 会在该阶段对类变量也称为静态变量static 关键字修饰的分配内存并初始化对应数据类型的默认初始值如 0、0L、null、false 等。 准备阶段是正式为类变量分配内存并设置类变量的初始值阶段即在方法区中分配这些变量所使用的内存空间。注意这里所说的初始值概念比如一个类变量定义为 public static int value1 123;实际上变量 value1 在准备阶段过后的初始值为 0 而不是 123如果是String类型初始值为null将 value1 赋值为 123 的 putstatic 指令是程序被编译后存放于类构造器方法之中。 但是注意如果声明为: public static final int value2 123;在编译阶段会为 value2 生成 ConstantValue 属性在准备阶段虚拟机会根据 ConstantValue 属性将 value2 赋值为 123。 也就是static final 修饰的变量被称作为常量和类变量不同。常量一旦赋值就不会改变了所以 value2 在准备阶段的值为 123 而不是 0。 1.4 解析 该阶段将常量池中的符号引用转化为直接引用。 what符号引用直接引用 符号引用以一组符号任何形式的字面量只要在使用时能够无歧义的定位到目标即可来描述所引用的目标。 在编译时Java 类并不知道所引用的类的实际地址因此只能使用符号引用来代替。比如 club.sscai.Test1 类引用了 club.sscai.Test2 类编译时 Test1 类并不知道 Test2 类的实际内存地址因此只能使用符号 club.sscai.Test2。 直接引用通过对符号引用进行解析找到引用的实际内存地址。 1.5 初始化 该阶段是类加载过程的最后一步。在准备阶段类变量已经被赋过默认初始值而在初始化阶段类变量将被赋值为代码期望赋的值。换句话说初始化阶段是执行类构造器方法的过程。 上面这段话说得比较抽象不好理解我来举个例子。 String niceyoo new String(感谢关注);上面这段代码使用了 new 关键字来实例化一个字符串对象那么这时候就会调用 String 类的构造方法对 niceyoo 进行实例化怎么个实例化就是赋值呗。 本节点总结 其实看完类加载过程由于大部分偏理论乏味的同时又很难理解也不容易记忆。所以将类加载过程结合面试题来进一步扩展如下 建议先思考后再看答案 题目一如下代码中执行 main 函数会通过编译吗如果可以通过打印结果是什么呢 public class A {public static void fun1(){System.out.println(fun1);}public void fun2(){System.out.println(fun2);}public static void main(String[] args){((A) null).fun1();((A) null).fun2();}}答案 首先代码是可以通过编译的null 可以强制转为任意类型调用其类中的静态方法 fun1 不报异常调用其类中的非静态方法 fun2 会报空指针异常。 分析 编译是否正常通过最大的干扰项应该是 null 强转吧估计有的小伙伴都不一定见过null 可以被强制类型转换成任意类型的对象知识点下次要考。 关于打印结果则主要是类加载过程的考察当加载类对象时首先初始化静态属性然后静态代码块当实例化对象时首先执行构造块直接写在类中的代码块{ xxx }然后执行构造方法。至于各静态块和静态属性初始化哪个些执行是按代码的先后顺序。属性、构造块、构造方法之间的执行顺序但构造块一定会在构造方法前执行也是按代码的先后顺序。 综上对象即便被将转为空时静态方法也是可以被调用的这也是我们平时在使用一些工具类时直接通过对象.来访问其方法的原因。 题目二请指出下面程序的运行结果。 class A {static {System.out.print(1);}public A() {System.out.print(2);} }class B extends A {static {System.out.print(a);}public B() {System.out.print(b);} }public class Hello {public static void main(String[] args) {A ab new B();ab new B();} } 分析 通过上一题目的分析中我们可能机智的得到了静态代码块是优于构造方法的执行的但是这个题目中出现了A\B类的继承关系所以可能带来困扰但是没关系静态代码块就是优于构造方法的只是父类优先级相对高一级罢了比如 new B() 会先调用父类 A 的静态代码块其次是 B 的静态代码块然后是 A 的构造方法最后是 B 的构造方法。 汇总执行顺序是先执行父类的静态代码块然后执行子类的静态代码块然后执行父类的非静态代码块再执行父类的构造方法之后再执行子类的非静态代码块再执行子类的构造方法。静态代码块非静态代码块构造方法。 再就是对象的创建只会调用一次静态代码块因为类初始化信息是存在方法区里当加载类的时候去检查第二次的时候它会发现已经初始化过了就不会再执行所以再去 new B() 的时候是不会再去打印 1a 的。 如果觉得比较绕再举个例子就好比你玩王者荣耀的时候有个赵云的6元首充礼包你第一次充钱创建了这个首充礼包的对象当你第二次充钱时就不会再有首充礼包了。 答案1a2b2b 2、类加载器 聊完类加载过程的五个阶段我们再来看看加载阶段用到的类加载器。 系统运行时是由类加载器将 .class 文件的二进制数据从外部存储器如光盘硬盘调入内存中CPU再从内存中读取指令和数据进行运算并将运算结果存入内存中的显然类加载器是很重要的第一步。 一般来说Java 程序员并不需要直接同类加载器进行交互。JVM 默认的行为就已经足够满足大多数情况的需求了。不过如果遇到了需要和类加载器进行交互的情况而对类加载器的机制又不是很了解的话就不得不花大量的时间去调试 ClassNotFoundException 和 NoClassDefFoundError 等异常。 对于任意一个类都需要由它的类加载器和这个类本身一同确定其在 JVM 中的唯一性。也就是说如果两个类的加载器不同即使两个类来源于同一个字节码文件那这两个类就必定不相等比如两个类的 Class 对象不 equals。 Java 类加载器可以分为三种 1启动类加载器Bootstrap Class-Loader加载 jre/lib 包下面的 jar 文件比如说常见的 rt.jar。 启动类加载器主要加载的是JVM自身需要的类这个类加载使用 C 语言实现的是虚拟机自身的一部分它负责将 JAVA_HOME/lib路径下的核心类库或-Xbootclasspath参数指定的路径下的jar包加载到内存中注意必由于虚拟机是按照文件名识别加载jar包的如rt.jar如果文件名不被虚拟机识别即使把jar包丢到lib目录下也是没有作用的(出于安全考虑Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类)。 2扩展类加载器Extension or Ext Class-Loader加载 jre/lib/ext 包下面的 jar 文件。 扩展类加载器是指Sun公司(已被Oracle收购)实现的sun.misc.Launcher$ExtClassLoader类由Java语言实现的是Launcher的静态内部类它负责加载JAVA_HOME/lib/ext目录下或者由系统变量-Djava.ext.dir指定位路径中的类库开发者可以直接使用标准扩展类加载器。 3应用类加载器Application or App Clas-Loader根据程序的类路径classpath来加载 Java 类。 也称应用程序加载器是指 Sun公司实现的sun.misc.Launcher$AppClassLoader。它负责加载系统类路径java -classpath或-D java.class.path 指定路径下的类库也就是我们经常用到的classpath路径开发者可以直接使用系统类加载器一般情况下该类加载是程序中默认的类加载器通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器。 来来来通过一段简单的代码了解下。 public class Test1 {public static void main(String[] args){ClassLoader currentLoader Test.class.getClassLoader();System.out.println(currentLoader.toString());ClassLoader parentLoader currentLoader.getParent();System.out.println(parentLoader.toString());ClassLoader parentParentLoader parentLoader.getParent();System.out.println(parentParentLoader);} }每个 Java 类都维护着一个指向定义它的类加载器的引用通过 类名.class.getClassLoader() 可以获取到此引用然后通过 .getParent() 可以获取类加载器的上层类加载器。 这段代码的输出结果如下 sun.misc.Launcher$AppClassLoader18b4aac2 sun.misc.Launcher$ExtClassLoader4554617c null第一行输出为 Test 的类加载器即应用类加载器它是 sun.misc.LauncherAppClassLoader∗∗类的实例第二行输出为扩展类加载器是∗∗sun.misc.LauncherAppClassLoader** 类的实例第二行输出为扩展类加载器是 **sun.misc.LauncherAppClassLoader∗∗ 类的实例第二行输出为扩展类加载器是 ∗∗sun.misc.LauncherExtClassLoader 类的实例。那启动类加载器呢按理说扩展类加载器的上层类加载器是启动类加载器但在我这个版本的 JDK 中 扩展类加载器的 getParent() 返回 null。 在 Java 的日常应用程序开发中类的加载几乎是由上述3种类加载器相互配合执行的在必要时我们还可以自定义类加载器需要注意的是Java 虚拟机对 class 文件采用的是按需加载的方式也就是说当需要使用该类时才会将它的 class 文件加载到内存生成 class 对象而且加载某个类的 class 文件时 Java 虚拟机采用的是双亲委派模式即把请求交由父类处理它一种任务委派模式下面我们进一步了解它。 别放弃加油 3、双亲委派模型 双亲委派模式是在 Java 1.2 后引入的其工作原理的是如果一个类加载器收到了类加载请求它并不会自己先去加载而是把这个请求委托给父类的加载器去执行如果父类加载器还存在其父类加载器则进一步向上委托依次递归请求最终将到达顶层的启动类加载器如果父类加载器可以完成类加载任务就成功返回倘若父类加载器无法完成此加载任务子加载器才会尝试自己去加载这就是双亲委派模式即每个儿子都很懒每次有活就丢给父亲去干直到父亲说这件事我也干不了时儿子自己想办法去完成这不就是传说中的实力坑爹啊那么采用这种模式有啥用呢? 双亲委派模式优势 采用双亲委派模式的是好处是 Java 类随着它的类加载器一起具备了一种带有优先级的层次关系通过这种层级关可以避免类的重复加载当父亲已经加载了该类时就没有必要子 ClassLoader 再加载一次。 其次是考虑到安全因素java 核心 api 中定义类型不会被随意替换假设通过网络传递一个名为 java.lang.Integer 的类通过双亲委托模式传递到启动类加载器而启动类加载器在核心 Java API 发现这个名字的类发现该类已被加载并不会重新加载网络传递的过来的 java.lang.Integer而直接返回已加载过的 Integer.class这样便可以防止核心API库被随意篡改。 可能你会想如果我们在 classpath 路径下自定义一个名为 java.lang.SingleInterge 类(该类是胡编的)呢该类并不存在 java.lang 中经过双亲委托模式传递到启动类加载器中由于父类加载器路径下并没有该类所以不会加载将反向委托给子类加载器加载最终会通过系统类加载器加载该类。但是这样做是不允许因为 java.lang 是核心 API 包需要访问权限强制加载将会报出如下异常 java.lang.SecurityException: Prohibited package name: java.lang文字内容太乏味上个例子吧我们通过自定义类加载器去证实双亲委派模式。 先简单了解一下这个类加载器的主要方法 loadClass该方法中的逻辑就是双亲委派模式的实现当类加载请求到来时先从缓存中查找该类对象如果存在直接返回如果不存在则交给该类加载去的父加载器去加载倘若没有父加载则交给顶级启动类加载器去加载最后倘若仍没有找到则使用findClass()方法去加载。 findClassfindClass()方法是在loadClass()方法中被调用的当loadClass()方法中父加载器加载失败后则会调用自己的findClass()方法来完成类加载这样就可以保证自定义的类加载器也符合双亲委托模式。 defineClass通过这个方法不仅能够通过class文件实例化class对象也可以通过其他方式实例化class对象defineClass()方法通常与findClass()方法一起使用一般情况下在自定义类加载器时会直接覆盖ClassLoader的findClass()方法并编写加载规则取得要加载类的字节码后转换成流然后调用defineClass()方法生成类的Class对象。 resolveClass使用该方法可以使用类的Class对象创建完成也同时被解析。前面我们说链接阶段主要是对字节码进行验证为类变量分配内存并设置初始值同时将字节码文件中的符号引用转换为直接引用。 自定义类加载器 MyClassLoader package club.sscai.test7; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream;/** * author:  niceyoo * blog:    https://cnblogs.com/niceyoo * desc:    自定义类加载器 */ public class MyClassLoader extends ClassLoader {private String path;/* 加载器的路径 */private String name;/* 类加载器名称 */public MyClassLoader(String path,String name){super();/* 让起同类加载器成为该类的父加载器 */this.name name;this.path path;}/*** 父类加载器构造方法* param parent* param path* param name*/public MyClassLoader(ClassLoader parent,String path,String name){super(parent);/* 显示指定父类加载器 */this.name name;this.path path;}/*** 加载我们自己定义的类通过我们自定义的这个 ClassLoader* 例如club.sscai.test7.Demo* param name* return* throws ClassNotFoundException*/Overrideprotected Class? findClass(String name) throws ClassNotFoundException {/* 读取 class 文件转换成二进制数组 */byte[] data readClassFileToByteArray(name);return this.defineClass(name,data,0,data.length);}Overridepublic String toString() {return this.name;}/*** 获取 .class 字节数组* 【读取 class 文件将类转换成二进制数组】*  club.sscai.test7.Demo *  F:/idea_workspace/test/Demo.class* param name* return*/private byte[] readClassFileToByteArray(String name) {InputStream is null;byte[] returnData null;name name.replace(\\.,/);String filePath this.path name .class;File file new File(filePath);ByteArrayOutputStream os new ByteArrayOutputStream();try {is new FileInputStream(file);int tep 0;while ((tep is.read()) ! -1){os.write(tep);}returnData os.toByteArray();} catch (Exception e) {e.printStackTrace();} finally {try {is.close();os.close();} catch (IOException e) {e.printStackTrace();}}return returnData;}Overrideprotected Class? loadClass(String name, boolean resolve) throws ClassNotFoundException {return super.loadClass(name, resolve);} }当前项目位于 F:\idea_workspace\Demo 当前项目中的干扰项 Demo.java package club.sscai.test7;/** * author:  niceyoo * blog:    https://cnblogs.com/niceyoo * desc:    干扰项Demo */ public class Demo {public Demo() {System.out.println(我是父加载器加载的Demo:Demo.class.getClassLoader());} }存放在 F:/idea_workspace/test/ 目录下的 Demo.java注意如下代码需要通过 javac 编译成 Demo.class public class Demo {public Demo(){System.out.println(Demo: this.getClass().getClassLoader());} }测试代码 TestDemo.java 如下 public class TestDemo {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {/* 参数一为读取class路径参数二为自定义类加载器名称 */MyClassLoader xwLoader new MyClassLoader(F:/idea_workspace/test/,xiaowang);Class? demo xwLoader.loadClass(Demo);demo.newInstance();} }执行 main 方法后会打印什么呢 Demo:xiaowang我们改一下测试代码 public class TestDemo {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {MyClassLoader xwLoader new MyClassLoader(F:/idea_workspace/test/,xiaowang);Class? demo xwLoader.loadClass(club.sscai.test7.Demo);demo.newInstance();} }再次执行会打印什么呢 我是父加载器加载的Demo:sun.misc.Launcher$AppClassLoader18b4aac2显然第二次并没有加载 F:/idea_workspace/test/ 目录下的 Demo而是执行了当前项目中的 Demo为什么 这就是双亲委派模式由于当前启动类 TestDemo 的父级是 AppClassLoader显然该包下已经加载过 Demo 类了所以不会再去加载目标 Demo 4、热部署与热加载扩展 上边算是说了一堆理论吧热部署、热加载则算是实际应用了相信这两者应该并不陌生或多或少的应该也有所了解吧。 热加载的实现原理主要依赖java的类加载机制在实现方式可以概括为在容器启动的时候起一条后台线程定时的检测类文件的时间戳变化如果类的时间戳变掉了则将类重新载入。 热部署原理类似但它是直接重新加载整个应用这种方式会释放内存比热加载更加干净彻底但同时也更费时间。 简单总结一下两者的区别与联系 Java热部署与热加载的联系 不重启服务器编译/部署项目基于Java的类加载器实现 Java热部署与热加载的区别 部署方式 – 热部署在服务器运行时重新部署项目 – 热加载在运行时重新加载class实现原理 – 热部署直接重新加载整个应用 – 热加载在运行时重新加载class使用场景 – 热部署更多的是在生产环境使用 – 热加载则更多的实在开发环境使用 想要实现热部署可以分以下三个步骤 销毁该自定义ClassLoader更新class类文件创建新的ClassLoader去加载更新后的class类文件。 相关代码 User没有被修改类 public class User {public void add() {System.out.println(addV1,没有修改过...);}}User更新类 public class User {public void add() {System.out.println(我把之前的user add方法修改啦!);}}自定义类加载器 public class MyClassLoader extends ClassLoader {Overrideprotected Class? findClass(String name) throws ClassNotFoundException {try {/* 文件名称 */String fileName name.substring(name.lastIndexOf(.) 1) .class;/* 获取文件输入流 */InputStream is this.getClass().getResourceAsStream(fileName);/* 读取字节 */byte[] b new byte[is.available()];is.read(b);/* 将byte字节流解析成jvm能够识别的Class对象 */return defineClass(name, b, 0, b.length);} catch (Exception e) {throw new ClassNotFoundException();}}}更新代码 public class Hotswap {public static void main(String[] args)throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException,SecurityException, IllegalArgumentException, InvocationTargetException, InterruptedException {loadUser();System.gc();Thread.sleep(1000);/* 等待资源回收 *//* 需要被热部署的class文件 */File file1 new File(F:\\test\\User.class);/* 之前编译好的class文件 */File file2 new File(F:\\idea_workspace\\target\\classes\\club\\sscai\\User.class);/* 删除旧版本的class文件 */boolean isDelete file2.delete();if (!isDelete) {System.out.println(热部署失败.);return;}file1.renameTo(file2);System.out.println(update success!);loadUser();}public static void loadUser() throws ClassNotFoundException, InstantiationException, IllegalAccessException,NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {MyClassLoader myLoader new MyClassLoader();Class? class1 myLoader.findClass(club.sscai.User);Object obj1 class1.newInstance();Method method class1.getMethod(add);method.invoke(obj1);System.out.println(obj1.getClass());System.out.println(obj1.getClass().getClassLoader());}}5、最后 本篇有点过长了其实大致看下来类加载无非也就那么回事。 类加载机制JVM 将类的信息动态添加到内存并使用的一种机制。
http://www.pierceye.com/news/884493/

相关文章:

  • 怎么看出网站是dede做的网页的响应式布局
  • 中国农村建设网站静安广州网站建设
  • 全国 做网站的企业wordpress+编辑模板
  • 网站开发需要的编程软件有哪些海门住房和城乡建设局网站
  • 南宁上林网站建设交换链接是什么
  • 什么网站做简历好api模式网站开发
  • 网站建设与管理专业好吗网络推广seo培训班
  • 常用网站架构辽宁建设工程信息网审计报告
  • 绿色大气网站模板坪山网站建设公司
  • 网站建设动态wordpress禁止自动升级
  • 网站建设网站建设平台网站建设费计入什么科目比较好
  • 豪圣建设项目管理网站公司网站设计与管理
  • 网站开发很难么交互网站图
  • 做网站用什么语音网站开发绪论
  • 中国建设银行徐州分行网站网站如何做视频教程
  • 烟台建站服务荥阳市建设局 网站
  • 网站备案登记推广网站案例
  • 企业网站设计论文摘要怎么写网络广告是什么意思
  • 自建站服务快应用 小程序
  • 上海网站建设过程邯郸网站建设推荐咨询
  • 公司有网站域名 如何做网站wordpress 字段
  • 做网站的类型东莞网页设计制作公司
  • 有品质的网站推广公司网站建设彩铃语
  • wordpress提示更新网站页面seo
  • 建设全国科技中心网站郑州百姓网官网
  • 漂亮网站wordpress 文章统计
  • 广西建设厅培训中心兰州seo网站排名
  • 布吉医院网站建设鞍山市网络销售平台
  • 开发一个网站系统报价wordpress文章摘要
  • 做脚本从网站引流外贸网站建设不可缺少的灵活性