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

电商网站开发主要设计内容2023年战争离我们越来越近了

电商网站开发主要设计内容,2023年战争离我们越来越近了,有没有在网上做ps赚钱的网站,wordpress 小清新笔记来源#xff1a;尚硅谷 JVM 全套教程#xff0c;百万播放#xff0c;全网巅峰#xff08;宋红康详解 java 虚拟机#xff09; 文章目录 7. 方法区7.1. 栈、堆、方法区的交互关系7.2. 方法区的理解7.2.1. 方法区在哪里#xff1f;7.2.2. 方法区的基本理解7.2.3. HotSp… 笔记来源尚硅谷 JVM 全套教程百万播放全网巅峰宋红康详解 java 虚拟机 文章目录 7. 方法区7.1. 栈、堆、方法区的交互关系7.2. 方法区的理解7.2.1. 方法区在哪里7.2.2. 方法区的基本理解7.2.3. HotSpot 中方法区的演进 7.3. 设置方法区大小与 OOM7.3.1. 设置方法区内存的大小7.3.2. 如何解决这些 OOM 7.4. 方法区的内部结构7.4.1. 方法区Method Area存储什么7.4.2. 方法区的内部结构类型信息域Field信息方法Method信息non-final 的类变量补充说明全局常量static final 7.4.3. 运行时常量池 VS 常量池为什么需要常量池常量池中有什么?小结 7.4.4. 运行时常量池 7.5. 方法区使用举例7.6. 方法区的演进细节7.6.1. 为什么永久代要被元空间替代7.6.2. StringTable 为什么要调整位置7.6.3. 静态变量存放在那里 7.7. 方法区的垃圾回收总结常见面试题 7. 方法区 从线程共享与否的角度来看 7.1. 栈、堆、方法区的交互关系 7.2. 方法区的理解 官方文档Chapter 2. The Structure of the Java Virtual Machine (oracle.com) 7.2.1. 方法区在哪里 《Java 虚拟机规范》中明确说明“尽管所有的方法区在逻辑上是属于堆的一部分但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于 HotSpotJVM 而言方法区还有一个别名叫做 Non-Heap非堆目的就是要和堆分开。 所以方法区看作是一块独立于 Java 堆的内存空间。 7.2.2. 方法区的基本理解 方法区Method Area与 Java 堆一样是各个线程共享的内存区域。方法区在 JVM 启动的时候被创建并且它的实际的物理内存空间中和 Java 堆区一样都可以是不连续的。方法区的大小跟堆空间一样可以选择固定大小或者可扩展。方法区的大小决定了系统可以保存多少个类如果系统定义了太多的类导致方法区溢出虚拟机同样会抛出内存溢出错误java.lang.OutOfMemoryError: PermGen space 或者java.lang.OutOfMemoryError: Metaspace 加载大量的第三方的 jar 包Tomcat 部署的工程过多30~50 个大量动态的生成反射类 关闭 JVM 就会释放这个区域的内存。 7.2.3. HotSpot 中方法区的演进 在 jdk7 及以前习惯上把方法区称为永久代。jdk8 开始使用元空间取代了永久代。 本质上方法区和永久代并不等价。仅是对 hotspot 而言的。《Java 虚拟机规范》对如何实现方法区不做统一要求。例如BEA JRockit / IBM J9 中不存在永久代的概念。 现在来看当年使用永久代不是好的 idea。导致 Java 程序更容易 OOM超过-XX:MaxPermsize上限 而到了 JDK8终于完全废弃了永久代的概念改用与 JRockit、J9 一样在本地内存中实现的元空间Metaspace来代替 元空间的本质和永久代类似都是对 JVM 规范中方法区的实现。不过元空间与永久代最大的区别在于元空间不在虚拟机设置的内存中而是使用本地内存 永久代、元空间二者并不只是名字变了内部结构也调整了 根据《Java 虚拟机规范》的规定如果方法区无法满足新的内存分配需求时将抛出 OOM 异常 7.3. 设置方法区大小与 OOM 7.3.1. 设置方法区内存的大小 方法区的大小不必是固定的JVM 可以根据应用的需要动态调整。 jdk7 及以前 通过-XX:Permsize来设置永久代初始分配空间。默认值是 20.75M通过-XX:MaxPermsize来设定永久代最大可分配空间。32 位机器默认是 64M64 位机器模式是 82M当 JVM 加载的类信息容量超过了这个值会报异常OutOfMemoryError:PermGen space。 JDK8 以后 元数据区大小可以使用参数 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize指定默认值依赖于平台。windows 下-XX:MetaspaceSize21M -XX:MaxMetaspaceSize-1//即没有限制。与永久代不同如果不指定大小默认情况下虚拟机会耗尽所有的可用系统内存。如果元数据区发生溢出虚拟机一样会抛出异常OutOfMemoryError:Metaspace-XX:MetaspaceSize设置初始的元空间大小。对于一个 64 位的服务器端 JVM 来说其默认的-XX:MetaspaceSize值为 21MB。这就是初始的高水位线一旦触及这个水位线Full GC 将会被触发并卸载没用的类即这些类对应的类加载器不再存活然后这个高水位线将会重置。新的高水位线的值取决于 GC 后释放了多少元空间。如果释放的空间不足那么在不超过MaxMetaspaceSize时适当提高该值。如果释放空间过多则适当降低该值。如果初始化的高水位线设置过低上述高水位线调整情况会发生很多次。通过垃圾回收器的日志可以观察到 Full GC 多次调用。为了避免频繁地 GC建议将-XX:MetaspaceSize设置为一个相对较高的值。 举例 1《深入理解 Java 虚拟机》的例子 举例 2 /*** jdk8中* -XX:MetaspaceSize10m-XX:MaxMetaspaceSize10m* jdk6中* -XX:PermSize10m-XX:MaxPermSize10m*/ public class OOMTest extends ClassLoader{public static void main(String[] args){int j 0;try{OOMTest test new OOMTest();for (int i0;i10000;i){//创建Classwriter对象用于生成类的二进制字节码ClassWriter classWriter new ClassWriter(0);//指明版本号public类名包名父类接口classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, Class i, nu1l, java/lang/Object, null);//返回byte[]byte[] code classWriter.toByteArray();//类的加载test.defineClass(Class i, code, 0, code.length); //CLass对象j;}} finally{System.out.println(j);}} }7.3.2. 如何解决这些 OOM 要解决 OOM 异常或 heap space 的异常一般的手段是首先通过内存映像分析工具如 Eclipse Memory Analyzer对 dump 出来的堆转储快照进行分析重点是确认内存中的对象是否是必要的也就是要先分清楚到底是出现了内存泄漏Memory Leak还是内存溢出Memory Overflow 如果是内存泄漏可进一步通过工具查看泄漏对象到 GC Roots 的引用链。于是就能找到泄漏对象是通过怎样的路径与 GCRoots 相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息以及 GCRoots 引用链的信息就可以比较准确地定位出泄漏代码的位置。 如果不存在内存泄漏换句话说就是内存中的对象确实都还必须存活着那就应当检查虚拟机的堆参数-Xmx与-Xms与机器物理内存对比看是否还可以调大从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况尝试减少程序运行期的内存消耗。 7.4. 方法区的内部结构 7.4.1. 方法区Method Area存储什么 《深入理解 Java 虚拟机》书中对方法区Method Area存储内容描述如下 它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。 7.4.2. 方法区的内部结构 类型信息 对每个加载的类型类 class、接口 interface、枚举 enum、注解 annotationJVM 必须在方法区中存储以下类型信息 这个类型的完整有效名称全名包名.类名这个类型直接父类的完整有效名对于 interface 或是 java.lang.object都没有父类这个类型的修饰符publicabstractfinal 的某个子集这个类型直接接口的一个有序列表 域Field信息 JVM 必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。 域的相关信息包括域名称、域类型、域修饰符publicprivateprotectedstaticfinalvolatiletransient 的某个子集 方法Method信息 JVM 必须保存所有方法的以下信息同域信息一样包括声明顺序 方法名称方法的返回类型或 void方法参数的数量和类型按顺序方法的修饰符publicprivateprotectedstaticfinalsynchronizednativeabstract 的一个子集方法的字节码bytecodes、操作数栈、局部变量表及大小abstract 和 native 方法除外异常表abstract 和 native 方法除外 每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引 non-final 的类变量 静态变量和类关联在一起随着类的加载而加载他们成为类数据在逻辑上的一部分类变量被类的所有实例共享即使没有类实例时你也可以访问它 public class MethodAreaTest {public static void main(String[] args) {Order order new Order();order.hello();System.out.println(order.count);} } class Order {public static int count 1;public static void hello() {System.out.println(hello!);} }补充说明全局常量static final 被声明为 final 的类变量的处理方法则不同每个全局常量在编译的时候就会被分配了。 7.4.3. 运行时常量池 VS 常量池 方法区内部包含了运行时常量池字节码文件内部包含了常量池要弄清楚方法区需要理解清楚 ClassFile因为加载类的信息都在方法区。要弄清楚方法区的运行时常量池需要理解清楚 ClassFile 中的常量池。 官方文档https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html 一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述符信息外还包含一项信息就是常量池表Constant Pool Table包括各种字面量和对类型、域和方法的符号引用 为什么需要常量池 一个 java 源文件中的类、接口编译后产生一个字节码文件。而 Java 中的字节码需要数据支持通常这种数据会很大以至于不能直接存到字节码里换另一种方式可以存到常量池这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池之前有介绍。 比如如下的代码 public class SimpleClass {public void sayHello() {System.out.println(hello);} }虽然只有 194 字节但是里面却使用了 String、System、PrintStream 及 Object 等结构。这里的代码量其实很少了如果代码多的话引用的结构将会更多这里就需要用到常量池了。 常量池中有什么? 击中常量池内存储的数据类型包括 数量值字符串值类引用字段引用方法引用 例如下面这段代码 public class MethodAreaTest2 {public static void main(String args[]) {Object obj new Object();} }Object obj new Object();将会被翻译成如下字节码 0: new #2 // Class java/lang/Object 1: dup 2: invokespecial // Method java/lang/Object init() V小结 常量池、可以看做是一张表虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型 7.4.4. 运行时常量池 运行时常量池Runtime Constant Pool是方法区的一部分。常量池表Constant Pool Table是 Class 文件的一部分用于存放编译期生成的各种字面量与符号引用这部分内容将在类加载后存放到方法区的运行时常量池中。运行时常量池在加载类和接口到虚拟机后就会创建对应的运行时常量池。JVM 为每个已加载的类型类或接口都维护一个常量池。池中的数据项像数组项一样是通过索引访问的。运行时常量池中包含多种不同的常量包括编译期就已经明确的数值字面量也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址了这里换为真实地址。运行时常量池相对于 Class 文件常量池的另一重要特征是具备动态性。运行时常量池类似于传统编程语言中的符号表symboltable但是它所包含的数据却比符号表要更加丰富一些。当创建类或接口的运行时常量池时如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值则 JVM 会抛 OutOfMemoryError 异常。 7.5. 方法区使用举例 public class MethodAreaDemo {public static void main(String args[]) {int x 500;int y 100;int a x / y;int b 50;System.out.println(ab);} }7.6. 方法区的演进细节 首先明确只有 Hotspot 才有永久代。BEA JRockit、IBMJ9 等来说是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节不受《Java 虚拟机规范》管束并不要求统一Hotspot 中方法区的变化 JDK1.6 及之前有永久代permanet静态变量存储在永久代上JDK1.7有永久代但已经逐步 “去永久代”字符串常量池静态变量移除保存在堆中JDK1.8无永久代类型信息字段方法常量保存在本地内存的元空间但字符串常量池、静态变量仍然在堆中。 7.6.1. 为什么永久代要被元空间替代 官网地址JEP 122: Remove the Permanent Generation (java.net) JRockit 是和 HotSpot 融合后的结果因为 JRockit 没有永久代所以他们不需要配置永久代 随着 Java8 的到来HotSpot VM 中再也见不到永久代了。但是这并不意味着类的元数据信息也消失了。这些数据被移到了一个与堆不相连的本地内存区域这个区域叫做元空间Metaspace。 由于类的元数据分配在本地内存中元空间的最大可分配空间就是系统可用内存空间。 这项改动是很有必要的原因有 为永久代设置空间大小是很难确定的。在某些场景下如果动态加载类过多容易产生 Perm 区的 oom。比如某个实际 Web 工 程中因为功能点比较多在运行过程中要不断动态加载很多类经常出现致命错误。 Exception in thread dubbo client x.x connector java.lang.OutOfMemoryError:PermGen space而元空间和永久代之间最大的区别在于元空间并不在虚拟机中而是使用本地内存。 因此默认情况下元空间的大小仅受本地内存限制。 对永久代进行调优是很困难的。 有些人认为方法区如 HotSpot 虚拟机中的元空间或者永久代是没有垃圾收集行为的其实不然。《Java 虚拟机规范》对方法区的约束是非常宽松的提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在如 JDK 11 时期的 ZGC 收集器就不支持类卸载。 一般来说这个区域的回收效果比较难令人满意尤其是类型的卸载条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前 Sun 公司的 Bug 列表中曾出现过的若干个严重的 Bug 就是由于低版本的 HotSpot 虚拟机对此区域未完全回收而导致内存泄漏 方法区的垃圾收集主要回收两部分内容常量池中废弃的常量和不再使用的类型 7.6.2. StringTable 为什么要调整位置 jdk7 中将 StringTable 放到了堆空间中。因为永久代的回收效率很低在 full gc 的时候才会触发。而 full gc 是老年代的空间不足、永久代不足时才会触发。 这就导致 StringTable 回收效率不高。而我们开发中会有大量的字符串被创建回收效率低导致永久代内存不足。放到堆里能及时回收内存。 7.6.3. 静态变量存放在那里 /*** 静态引用对应的对象实体始终都存在堆空间* jdk7:* -Xms200m -Xmx200m -XX:PermSize300m -XX:MaxPermSize300m -XX:PrintGCDetails* jdk8:* -Xms200m -Xmx200m-XX:MetaspaceSize300m -XX:MaxMetaspaceSize300m -XX:PrintGCDetails*/ public class StaticFieldTest {private static byte[] arr new byte[1024 * 1024 * 100];public static void main(String[] args) {System.out.println(StaticFieldTest.arr);try {Thread.sleep(1000000);} catch (InterruptedException e){e.printStackTrace();}} }/** * staticobj、instanceobj、Localobj存放在哪里 */public class StaticobjTest { static class Test { static ObjectHolder staticobj new ObjectHolder(); ObjectHolder instanceobj new ObjectHolder(); void foo(){ ObjectHolder localobj new ObjectHolder(); System.out.println(done); } } private static class ObjectHolder{ public static void main(String[] args) { Test test new StaticobjTest.Test(); test.foo(); } }}使用 JHSDB 工具进行分析这里细节略掉 staticobj 随着 Test 的类型信息存放在方法区instanceobj 随着 Test 的对象实例存放在 Java 堆localobject 则是存放在 foo()方法栈帧的局部变量表中。 测试发现三个对象的数据在内存中的地址都落在 Eden 区范围内所以结论只要是对象实例必然会在 Java 堆中分配。 接着找到了一个引用该 staticobj 对象的地方是在一个 java.lang.Class 的实例里并且给出了这个实例的地址通过 Inspector 查看该对象实例可以清楚看到这确实是一个 java.lang.Class 类型的对象实例里面有一个名为 staticobj 的实例字段 从《Java 虚拟机规范》所定义的概念模型来看所有 Class 相关的信息都应该存放在方法区之中但方法区该如何实现《Java 虚拟机规范》并未做出规定这就成了一件允许不同虚拟机自己灵活把握的事情。JDK7 及其以后版本的 HotSpot 虚拟机选择把静态变量与类型在 Java 语言一端的映射 class 对象存放在一起存储于 Java 堆之中从我们的实验中也明确验证了这一点 7.7. 方法区的垃圾回收 有些人认为方法区如 Hotspot 虚拟机中的元空间或者永久代是没有垃圾收集行为的其实不然。《Java 虚拟机规范》对方法区的约束是非常宽松的提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在如 JDK11 时期的 zGC 收集器就不支持类卸载。 一般来说这个区域的回收效果比较难令人满意尤其是类型的卸载条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前 sun 公司的 Bug 列表中曾出现过的若干个严重的 Bug 就是由于低版本的 HotSpot 虚拟机对此区域未完全回收而导致内存泄漏。 方法区的垃圾收集主要回收两部分内容常量池中废弃的常量和不再使用的类型。 先来说说方法区内常量池之中主要存放的两大类常量字面量和符号引用。字面量比较接近 Java 语言层次的常量概念如文本字符串、被声明为 final 的常量值等。而符号引用则属于编译原理方面的概念包括下面三类常量 类和接口的全限定名字段的名称和描述符方法的名称和描述符 HotSpot 虚拟机对常量池的回收策略是很明确的只要常量池中的常量没有被任何地方引用就可以被回收。 回收废弃常量与回收 Java 堆中的对象非常类似。 判定一个常量是否“废弃”还是相对简单而要判定一个类型是否属于“不再被使用的类”的条件就比较苛刻了。需要同时满足下面三个条件 该类所有的实例都已经被回收也就是 Java 堆中不存在该类及其任何派生子类的实例。 加载该类的类加载器已经被回收这个条件除非是经过精心设计的可替换类加载器的场景如 OSGi、JSP 的重加载等否则通常是很难达成的。 该类对应的 java.lang.Class 对象没有在任何地方被引用无法在任何地方通过反射访问该类的方法。 Java 虚拟机被允许对满足上述三个条件的无用类进行回收这里说的仅仅是“被允许”而并不是和对象一样没有引用了就必然会回收。关于是否要对类型进行回收HotSpot 虚拟机提供了-Xnoclassgc参数进行控制还可以使用-verbose:class 以及 -XX:TraceClassLoading、-XX:TraceClassUnLoading查看类加载和卸载信息 在大量使用反射、动态代理、CGLib 等字节码框架动态生成 JSP 以及 OSGi 这类频繁自定义类加载器的场景中通常都需要 Java 虚拟机具备类型卸载的能力以保证不会对方法区造成过大的内存压力。 总结 常见面试题 百度 说一下 JVM 内存模型吧有哪些区分别干什么的 蚂蚁金服 Java8 的内存分代改进 JVM 内存分哪几个区每个区的作用是什么 一面JVM 内存分布/内存结构栈和堆的区别堆的结构为什么两个 survivor 区 二面Eden 和 survior 的比例分配 小米 jvm 内存分区为什么要有新生代和老年代 字节跳动 二面Java 的内存分区 二面讲讲 vm 运行时数据库区 什么时候对象会进入老年代 京东 JVM 的内存结构Eden 和 Survivor 比例。 JVM 内存为什么要分成新生代老年代持久代。 新生代中为什么要分为 Eden 和 survivor。 天猫 一面Jvm 内存模型以及分区需要详细到每个区放什么。 一面JVM 的内存模型Java8 做了什么改 拼多多 JVM 内存分哪几个区每个区的作用是什么 美团 java 内存分配 jvm 的永久代中会发生垃圾回收吗 一面jvm 内存分区为什么要有新生代和老年代
http://www.zqtcl.cn/news/133955/

相关文章:

  • 做地方网站需要什么部门批准天津专业做标书
  • 域名注册信息查询网站推广seo是什么
  • 做外贸网站哪家公司好常见的管理系统
  • 网站设计报价方案微信公众号外包
  • 网站设计遇到难题wordpress qq 微博
  • 网站模板种类长沙seo推广优化
  • 郑州网络建站公司wordpress安装及配置
  • 福州移动网站建设公司注册地址怎么写
  • 网站线上投票怎样做做铁艺需要什么网站
  • 襄阳营销型网站建设网站开发语言排行榜
  • 网站架构演变流程淄博亿泰
  • 电子商务网站功能介绍招商网站建设
  • 哈尔滨模板网站建站市场监督管理局12315
  • 做网站图片处理问题淘宝客推广
  • 科目一速成网站建设适合网络科技的公司名字
  • 解决网站兼容性问题网站关于我们怎么做
  • 网站建设教学视频百度云盘wap什么意思网络语言
  • 做psd模板下载网站搜索网站哪个好
  • 企业排名重庆网站seo优化
  • 怎么做免费域名网站永兴网站建设
  • 网站seo新手台州公司网站外包
  • html简单网站成品免费网站编辑属于什么行业
  • 装修网站设计平台景区网站建设策划案
  • 哪些网站布局设计做的比较好的商洛市城乡建设规划局网站
  • dw中旅游网站怎么做简单大气网站源码
  • 物流网站建设模板黄页网站推广app免费下载
  • iis添加网站的物理路径有资源的公众号
  • 答建设网站建网站的设备
  • 网站新闻专题怎么做python 做网站 用哪个框架好
  • 聊城做网站做的不错的网页链接打不开