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

宿州酒店网站建设wordpress邮箱验证配置文件

宿州酒店网站建设,wordpress邮箱验证配置文件,烟台网站公众号制作,网站建设山东目录 前言一、基础概念二、反射三、类加载器ClassLoader四、JVM内存模型后记 前言 本篇主要介绍Java虚拟机——JVM的相关内容。 “基础知识”是本专栏的第一个部分#xff0c;本篇博文是第四篇博文#xff0c;如有需要#xff0c;可#xff1a; 点击这里#xff0c;返回… 目录 前言一、基础概念二、反射三、类加载器ClassLoader四、JVM内存模型后记 前言 本篇主要介绍Java虚拟机——JVM的相关内容。 “基础知识”是本专栏的第一个部分本篇博文是第四篇博文如有需要可 点击这里返回本专栏的索引文章点击这里返回上一篇《【Java校招面试】基础知识三——多线程与并发》点击这里前往下一篇《【Java校招面试】基础知识五——GC》 一、基础概念 01. Java代码的Compile once, run anywhere是怎么实现的 所谓Compile once, run anywhere即一次编译随处运行。 Java源码首先被编译成字节码再由不同平台的JVM进行解析Java语言在不同的平台上运行时不需要进行重新编译Java虚拟机在执行字节码的时候把字节码转换成具体平台上的机器指令。 02. 为什么不直接将源码解析成机器码去执行 1) 准备工作: 每次执行前都需要各种检查降低执行效率 2) 兼容性: 可以将别的语言编译成字节码然后用JVM执行提高兼容性。 03. JVM如何加载.class文件 JVM主要由Class Loader、Runtime Data Area、Execution Engine和Native Interface组成。 Class Loader: 依据特定格式加载class文件到内存Execution Engine: 对命令进行解析Native Interface: 融合不同开发语言的原生库为Java所用Runtime Data Area: JVM内存空间结构模型 二、反射 Java反射机制是在运行状态中对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意方法和属性。 01. 反射的代码示例 1) 目标类包含一个私有属性、一个私有方法、一个公有方法注意包名 package reflecttest;public class Target {// 目标类私有属性private String privateField;// 目标类公有方法public void publicMethod(String param) {System.out.println(Im the public method of Target class.The param is param);}// 目标类私有方法private void privateMethod(String param) {System.out.println(Im the private method of Target class.The param is param);}}2) 反射调用类 public class ReflectTest {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class targetClass Class.forName(reflecttest.Target);Target target (Target) targetClass.newInstance();// 通过反射引用目标类私有属性testPrivateField(targetClass, target);// 通过反射调用目标类公有方法testPublicMethod(targetClass, target);// 通过反射调用目标类私有方法testPrivateMethod(targetClass, target);}private static void testPrivateField(Class clazz, Target target) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {Field privateField clazz.getDeclaredField(privateField);privateField.setAccessible(true);System.out.println(The Origin Value of Private Field Is: privateField.get(target));privateField.set(target, New Value);System.out.println(The Fixed Value of Private Field Is: privateField.get(target));}private static void testPublicMethod(Class clazz, Target target) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {Method publicMethod clazz.getMethod(publicMethod, String.class);publicMethod.invoke(target, \Calling Public Method.\);}private static void testPrivateMethod(Class clazz, Target target) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {Method privateMethod clazz.getDeclaredMethod(privateMethod, String.class);privateMethod.setAccessible(true);privateMethod.invoke(target, \Calling Private Method.\);}}3) 输出结果 The Origin Value of Private Field Is: null The Fixed Value of Private Field Is: New Value Im the public method of Target class. The param is Calling Public Method. Im the private method of Target class. The param is Calling Private Method.4) 总结   ① 流程: 先通过完全限定类名获得类对象然后newInstance获取实例该实例用于方法的invoke和属性的set等各种操作   ② getDeclaredMethod可以获得类的所有方法但不能获取继承的和实现的接口函数getMethod只可以获取public方法但也可以获取继承的public方法和实现的接口中的方法。对于Field同理   ③ 对私有的属性或者方法进行操作时需要setAccessable(true)改变访问权限。 三、类加载器ClassLoader ClassLoader的主要工作在Class装载的加载阶段其主要作用是从系统外部获得Class二进制数据流并装载进系统然后交给JVM进行连接、初始化等操作。 01. 类从编译到执行的过程 1) 编译器将Test.java源文件编译成Test.class字节码文件 2) ClassLoader将字节码转换为JVM中的Class对象 3) JVM利用Class对象实例化Test对象。 02. ClassLoader的类型 1) BootstrapClassLoader: 启动类加载器   ① 使用C编写   ② 负责加载Java核心库如java.lang;   ③ 无法直接获取 2) ExtClassLoader: 扩展类加载器   ① 使用Java编写   ② 负责加载jdk_home/lib/ext目录下的jar 3) AppClassLoader: 应用类加载器   ① 使用Java编写   ② 负责加载程序所在目录。 4) 自定义ClassLoader 03. 自定义ClassLoader的例子 1) 要加载的目标类 public class Target {static {System.out.println(Im Static Block of Target Class.);}}2) 自定义ClassLoader public class MyClassLoader extends ClassLoader {private String classPath;public MyClassLoader(String classPath) {this.classPath classPath;}Overrideprotected Class? findClass(String name) throws ClassNotFoundException {byte[] clazz loadClassFromFile(name);return defineClass(name, clazz, 0, clazz.length);}public byte[] loadClassFromFile(String className) {String path classPath File.separator className .class;try (InputStream in new FileInputStream(new File(path));ByteArrayOutputStream out new ByteArrayOutputStream();) {int c;while ((c in.read())! -1)out.write(c);return out.toByteArray();} catch (Exception ex) {return null;}}}3) ClassLoader调用类 public class ClassLoaderTest {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {String classPath /path/to/class/loader;MyClassLoader classLoader new MyClassLoader(classPath);Class c classLoader.loadClass(Target);c.newInstance();}}4) 输出结果 Im Static Block of Target Class.04. ClassLoader双亲委派机制 1) AppClassLoader的父类是ExtClassLoaderExtClassLoader的父类是BootstrapClassLoader 2) loadClass方法源码 protected synchronized 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);}}if (resolve) {resolveClass(c);}return c;}3) 程序逻辑——双亲委派机制 首先找缓存findLoadedClass没有的话就判断有没有parent有的话就用parent来递归的loadClass然而ExtClassLoader并没有设置parent则会通过findBootstrapClassOrNull来加载class而findBootstrapClassOrNull则会通过JNI方法private native Class findBootstrapClass(String name)来使用BootStrapClassLoader来加载class。然后如果parent未找到class则会调用findClass来加载classfindClass是一个protected的空方法可以覆盖它以便自定义class加载过程。 05. 使用双亲委派机制为什么是安全的 举个例子ClassLoader加载的class文件来源很多比如编译器编译生成的class、或者网络下载的字节码。而一些来源的class文件是不可靠的比如我可以自定义一个java.lang.Integer类来覆盖jdk中默认的Integer类例如下面这样 package java.lang;public class Integer {public Integer(int value) {System.exit(0);}}初始化这个Integer的构造器是会退出JVM破坏应用程序的正常进行。 如果使用双亲委派机制的话该Integer类永远不会被调用。因为委托BootStrapClassLoader加载后会加载JDK中的Integer类而不会加载自定义的这个因此就保证了安全性。 06. 类的加载方式 1) 隐式加载: new程序在运行过程中遇到需要用new生成对象时隐式调用类加载器将对应的类加载到JVM中。 2) 显式加载: loadClassforName等 区别 1) 显式加载需要先获取类对象然后调用其newInstance方法获取对象而隐式加载不需要 2) new支持调用目标类带参数的构造方法而newInstance方法则不支持传入参数。 07. 类的装载过程 1) 加载: 通过ClassLoader加载class文件字节码生成Class对象 2) 链接:   ① 校验: 检查加载的类的正确性和安全性   ② 准备: 为类变量分配存储空间并设置类变量初始值   ③ 解析: JVM将常量池中的符号引用转换为直接引用。 3) 初始化: 执行类变量赋值和静态代码块 08. loadClass和forName的区别 1) Class.forName得到的class是已经初始化完成的 2) ClassLoader.loadClass得到的class是还没有链接的。 应用场景 1) 有的类有静态代码块如mysql-connector因此需要使用Class.forName 2) Spring中由于IoC大量使用LazyLoad技术即延时加载在bean真正被调用时才完成初始化。这里用到的是ClassLoader.loadClass。 四、JVM内存模型 01. 从线程的角度看JVM内存模型 线程私有的内存: 程序计数器、虚拟机栈、本地方法栈所有线程共享的内存: 元空间MetaSpace、常量池、堆 1) 程序计数器Program Counter Register: 一块较小的内存空间是当前线程所执行的字节码行号指示器 逻辑计数器。改变计数器的值来选取下一条需要执行的字节码指令。和线程是一对一关系即线程私有对Java方法记录的是正在执 行的虚拟机字节码指令的地址对Native方法其值为Undefined。 由于只记录行号不会发生内存泄漏。 2) 虚拟机栈Stack: 是Java方法执行的内存模型。每个方法被执行时都会 创建一个栈帧方法运行期间的基础数据结构。   ① 局部变量表和操作数栈   局部变量表: 包含方法执行过程中的所有变量   操作数栈: 入栈、出栈、复制、交换、产生/消费变量   ② 通过一个简单的加法函数例子来深入理解 public static int add(int a, int b){int c 0;c a b;return c;}假设对add方法传入(1, 2)其过程为   ③ 递归为什么会引发java.lang.StackOverflowError异常   递归过深栈帧数超出虚拟栈的深度。解决方法限制递归深度或者换用迭代方法。   ④ 总结: 方法执行完成后栈帧会被自动释放掉因此不需要GC来回收。 3) 本地方法栈: 与虚拟机栈类似主要作用于标注了native的方法。 4) 元空间Meta Space: JDK 8中把类的元数据放在元空间而JDK 7及以前的版本是放在永久代PermGen中。   MetaSpace与PermGen相比的优势:   ① 元空间使用本地内存永久代使用jvm内存   ② 字符串常量池存在永久代中容易出现性能问题和内存溢出Meta Space没有了字符串常量池它被移动到了堆中   ③ 类和方法的信息大小难以确定给永久代的大小指定带来困难   ④ 永久代会为GC带来不必要的复杂性回收效率偏低   ⑤ 方便HotSpot与其他JVM如Jrockit的集成。 5) 堆Heap: 对象实例的分配区域GC管理的主要区域 02. 从存储的角度看JVM内存模型 1) JVM三大性能调优参数-Xms、-Xmx、-Xss的含义 -Xms堆大小的初始值-Xmx堆大小能扩容的最大值-Xss规定了每个线程虚拟机栈堆栈的大小 通常-Xms和-Xmx设置成一样的因为在堆扩容时会发生内存抖动影响程序运行时的稳定性。 2) 内存分配策略 静态存储: 编译时确定每个数据目标在运行时的存储空间需求栈式存储: 数据区需求在编译时未知运行时模块入口已确定堆式存储: 编译时或运行时模块入口都无法确定动态分配。 3) Java内存模型中堆和栈的区别 联系: 引用对象、数组时栈里定义变量保存堆中目标的首地址 区别   ① 管理方式: 栈自动释放堆需要GC   ② 空间大小: 一般情况下栈比堆小   ③ 碎片相关: 栈产生的碎片远小于堆   ④ 分配方式: 栈支持静态和动态分配堆仅支持动态分配   ⑤ 效率: 栈的效率比堆高。 4) Meta Space、堆、线程独占部分的联系 一个HelloWorld的例子 public class HelloWorld{private String String name;public void setName(String name){this.name name;}public void sayHello(){System.out.println(Hello name);}public static void main(String[] args){int a 1;HelloWorld hw new HelloWorld();hw.setName(test);hw.sayHello();}}内存分配 5) JDK 6和JDK 6中intern方法的区别 String s new String(Test);s.intern();JDK 6: 当调用intern方法时如果字符串常量池已创建该字符串对象则返回池中的该字符串的引用。否则将此字符串对象添加到字符串常量池中并返回该字符串对象的引用。JDK 6: 当调用intern方法时如果字符串常量池已创建该字符串对象则返回池中的该字符串的引用。否则如果该字符串对象已经存在于Java堆中则将堆中对此对象的引用添加到字符串常量池并且返回该引用如果堆中不存在则在池中创建该字符串并返回其引用。 6) 不同JDK中intern方法的功能区别   ① 代码 public static void main(String[] args){String s new String(a);s.intern();String s2 a;System.out.println(s s2);String s3 new String(a) new String(a);s3.intern();String s4 aa;System.out.println(s3 s4);}② JDK 6中输出结果false、false   PermGen只存放堆中的副本不能存放引用所以s3s4是false   ③ JDK 6中输出结果false、true   堆中的字符串常量池可以存放字符串的引用所以s3s4为true 03. 对象在内存中的布局 1) 对象头Header: 对象头分为Mark Word和Class Metadata Address两部分如果对象类型是数组还要有第三个部分Array Length即数组长度。 长度内容说明32/64 bitsMark Word存储对象的hashCode或锁信息等32/64 bitsClass Metadata Address存储对象类型数据的指针32 bitsArray Length数组长度如果对象类型是数组 Mark Word被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的 数据它会根据对象的状态复用自己的存储空间。 ① 在32位的HotSpot虚拟机中如果对象处于未被锁定的状态下那么Mark Word的32bit空间中的25bit用于存储对象哈希码4bit用于存储对象分代年龄2bit 用于存储锁标志位1bit固定为0。 锁状态25 bits4 bits1 bit是否是偏向锁2 bits锁标志位无锁对象的hashCode对象的分代年龄001 ② 在 32 位系统下存放 Class 指针的空间大小是 4 字节Mark Word 空间大小也是4字节因此头部就是 8 字节如果是数组就需要再加 4 字节表示数组的长度。 锁状态25 bits4 bits1 bit2 bits23 bits2 bits是否是偏向锁锁标志位轻量级锁指向栈中锁记录的指针00重量级锁指向互斥量重量级锁的指针10GC标记空11偏向锁线程IDEpoch对象分代年龄101 ③ 在64位系统及64位JVM下开启指针压缩那么头部存放Class指针的空间大小还是4字节而Mark Word区域会变大变成8字节也就是头部最少为12字节。 锁状态25 bits31 bits1 bit4 bits1 bit2 bitscms free分代年龄偏向锁锁标志位无锁unusedhashCode001偏向锁ThreadID(54 bits), Epoch(2 bits)101 2) 实例数据Instance Data: 实例数据部分是对象真正存储的有效信息也是在程序代码中所定义的各种类型的字段内容。这部分的存储顺序会受到虚拟机分配策略参数FieldsAllocationStyle和字段在 Java源码中定义顺序的影响。 3) 对齐填充Padding: 不是必然存在的没有特别的含义它仅起到占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍也就是说对象的大小必须是8字节的整数倍。对象头部分是8字节的倍数所以当对象实例数据部分没有对齐时就需要通过对齐填充来补全。 后记 JVM的知识点也不少为便于阅读我将其分为了基础概念、反射、类加载器ClassLoader和JVM内存模型4个部分。
http://www.hkea.cn/news/14358072/

相关文章:

  • 专做蔬菜大棚的网站网页制作工具可以分为
  • 企业手机网站建设推广怎样修改网站标题
  • 具有口碑的柳州网站建设推荐东莞常平中学
  • 黄骅网站建设php如何网站做修改
  • 网站的维护微软雅黑适合于做网站吗
  • 河北省住房和城身建设厅网站网站建设个人简历
  • 创建站点的基本步骤企业网站开发课程设计报告
  • 网站建设的软件门户网站建设考核总结
  • 巴州建设局网站网上购物系统
  • 查做外贸客户的网站海外人才招聘网
  • 中山网站建设价格硬件开发是干嘛的
  • 谷歌官方建站服务网站建设需要掌握什么技术
  • 怎么让公司网站随便就搜的到查询公司信息
  • 做网站需要多少钱卖片可以吗建站工作室
  • 微网站设计与开发企业logo设计含义
  • 有做不锈钢工程的网站购物网站名字
  • 专业的龙岗网站建设开发项目管理工具
  • wordpress自动广告位seo是搜索引擎优化吗
  • 无锡网站服务公司永久建站平台
  • 杭州网站建设品牌什么软件能搜索关键词能快速找到
  • 梅江区住房和城乡建设局官方网站wordpress怎么样
  • 织梦网站百度推送加哪网站排名易下拉霸屏
  • 网站建设带主机wordpress雄欲
  • 网站建设前期分析的内容可信赖的武进网站建设
  • 旗袍网站架构广州网络推广服务商
  • 深圳做网站的公司那个好中交建设集团 网站
  • 防止网站扫描组织建设内容
  • 织梦手机网站教程视频教程网站代理最快最干净
  • 买做指甲的材料在哪个网站哪里找做网站的客户
  • 自己做营销网站发表评论的wordpress网站模板