网站编程入门,西昌有哪些做网站的公司,教学直播平台网站建设费用,wordpress黑暗运行时区域1.程序计数器程序计数器#xff08;Program Counter Register#xff09;是一块较小的内存空间#xff0c;它可以看作是当前线程所执行的字节码的行号指示器。在虚拟机概念模型里#xff08;概念模型#xff0c;各种虚拟机可能会通过一些更高效的方式实现#…运行时区域1.程序计数器程序计数器Program Counter Register是一块较小的内存空间它可以看作是当前线程所执行的字节码的行号指示器。在虚拟机概念模型里概念模型各种虚拟机可能会通过一些更高效的方式实现字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令分支、跳转、循环、异常处理、线程恢复等基础操作都会依赖这个计数器来完成。每个线程都有独立的程序计数器用来在线程切换后能恢复到正确的执行位置各条线程之间的计数器互不影响独立存储。所以它是一个“线程私有”的内存区域。此内存区域是唯一一个在JVM规范中没有规定任何OutOfMemoryError情况的区域。2.虚拟机栈JVM栈是线程私有的内存区域。它描述的是java方法执行的内存模型每个方法执行的同时都会创建一个栈帧Stack Frame用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至完成的过程都对应着一个栈帧从入栈到出栈的过程。每当一个方法执行完成时该栈帧就会弹出栈帧的元素作为这个方法的返回值并且清除这个栈帧Java栈的栈顶的栈帧就是当前正在执行的活动栈也就是当前正在执行的方法。就像是组成动画的一帧一帧的图片方法的调用过程也是由栈帧切换来产生结果。 很多开发人员会把Java内存分为堆内存Heap和栈内存Stack这种划分的流行只能说明大多数开发人员最关注、与对象内存分配关系最密切的内存区域是这两块其中所指的“堆”在后面会讲到而所指的“栈”就是JVM栈或者说是JVM栈中的局部变量表部分。实际上Java内存区域的划分远比这要复杂。局部变量表存放了编译器可知的各种基本数据类型int、short、byte、char、double、float、long、boolean、对象引用reference类型它不等同于对象本身可能是一个指向对象起始地址的引用指针也可能是指向一个代表对象的句柄或其他与此对象相关的位置和returnAddress类型指向了一跳字节码指令的地址。 在JVM规范中对这个区域规定了两种异常情况如果线程请求的栈深度大于虚拟机允许的深度将抛出StackOverflowError异常如果虚拟机栈可以动态扩展在扩展时无法申请到足够的内存就会抛出OutOfMemoryError异常。3.本地方法栈本地方法栈和虚拟机栈所发挥的作用是很相似的它们之间的区别不过是 虚拟机栈为虚拟机执行Java方法字节码服务而本地方法栈则为虚拟机使用到的Native方法服务。Sun HotSpot 直接就把本地方法栈和虚拟机栈合二为一。本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。4.Java堆对于大多数应用来说Java堆Heap是JVM所管理的内存中最大的一块。它是被所有线程共享的一块内存区域在虚拟机启动时创建。主要用来存放对象实例所有的对象实例以及数组都要在堆上分配。堆是垃圾收集器管理的主要区域也被称为“GC堆”从内存回收的角度来看堆可以细分为新生代和老年代再细致一点可分为Eden空间、From Survivor空间、To Survivor空间空间分配比例是811。如果在堆中没有内存完成实例分配并且堆也无法再扩展时将抛出OutOfMemoryError异常。5.方法区方法区Method Area与堆一样也是各个线程共享的区域存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据也就是用来存储类的描述信息—元数据的。方法区是堆的一个逻辑部分为了区分Java堆它还有一个别名Non-Heap非堆。相对而言GC对于这个区域的收集是很少出现的。当方法区无法满足内存分配需求时将抛出OutOfMemoryError异常。在Java 7及之前版本我们也习惯称它为“永久代”Permanent Generation更确切来说应该是“HotSpot使用永久代实现了方法区”。需要注意的是从Java 8开始“永久代”已经被彻底移除使用了一个元空间Metaspace来代替它后面我们会详细讲解。6.运行时常量池运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池( Constant pool table)用于存放编译期生成的各种字面量和符号引用这部分内容将在类加载后进入运行时常量池中存放。运行时常量池相对于class文件常量池的另外一个特性是具备动态性java语言并不要求常量一定只有编译器才产生也就是并非预置入class文件中常量池的内容才能进入方法区运行时常量池运行期间也可能将新的常量放入池中。在近三个JDK版本1.6、1.7、1.8中 运行时常量池Runtime Constant Pool的所处区域一直在不断的变化在JDK1.6时它是方法区的一部分1.7又把他放到了堆内存中1.8之后出现了元空间它又回到了方法区。其实这也说明了官方对“永久代”的优化从1.7就已经开始了。7.直接内存直接内存Direct Memory并不是虚拟机运行时数据区的一部分也不是JVM规范中定义的内存区域。但这部分内存也被频繁的使用而且也可能导致OutOfMemoryError异常出现。它在JDK中最直观的表现就是NIO基于通道Channel与缓冲区Buffer的I/O方式它可以使用Native函数库直接分配堆外内存然后通过一个存储在Java堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能因为避免了在Java堆和Native堆中来回复制数据。从GC的角度看内存管理年轻代、老年代、方法区老年代由元空间替换从Java8开始HotSpot已经完全将永久代Permanent Generation移除取而代之的是一个新的区域—元空间MetaSpace它使用本地内存来存储类元数据信息。也就是说只要本地内存足够它不会出现像永久代中“java.lang.OutOfMemoryError: PermGen space”这种错误。同样的对永久代的设置参数 PermSize 和 MaxPermSize 也会失效。默认情况下“元空间”的大小可以动态调整或者使用新参数MaxMetaspaceSize 来限制本地内存分配给类元数据的大小。为什么叫元空间是因为这里面存储的是类的元数据信息。元数据Meta Date关于数据的数据或者叫做用来描述数据的数据或者叫做信息的信息。这些定义都很是抽象我们可以把元数据简单的理解成最小的数据单位。元数据可以为数据说明其元素或属性名称、大小、数据类型、等或其结构长度、字段、数据列或其相关数据位于何处、如何联系、拥有者。为什么要移除永久代用元空间取代呢1.静态变量将会从永久代移除, 放入Java heap或者native memory. 其中建议JVM的实现中将类的元数据放入 native memory, 将字符串池和类的静态变量放入Java堆中. 这样可以加载多少类的元数据就不在由MaxPermSize控制, 而由系统的实际可用空间来控制.2.为什么这么做呢? 字符串存在永久代中容易出现性能问题和内存溢出。类及方法的信息等比较难确定其大小因此对于永久代的大小指定比较困难太小容易出现永久代溢出太大则容易导致老年代溢出。永久代会为 GC 带来不必要的复杂度并且回收效率偏低。减少OOM只是表因, 更深层的原因还是要合并HotSpot和JRockit的代码, JRockit从来没有一个叫永久代的东西, 但是运行良好, 也不需要开发运维人员设置这么一个永久代的大小.元空间特色充分利用了Java语言规范类及相关的元数据的生命周期与类加载器的一致。每个类加载器都有它的内存区域-元空间只进行线性分配不会单独回收某个类除了重定义类 RedefineClasses 或类加载失败没有GC扫描或压缩元空间里的对象不会被转移如果GC发现某个类加载器不再存活会对整个元空间进行集体回收GCFull GC时指向元数据指针都不用再扫描减少了Full GC的时间。很多复杂的元数据扫描的代码尤其是CMS里面的那些都删除了。元空间只有少量的指针指向Java堆。这包括类的元数据中指向java.lang.Class实例的指针;数组类的元数据中指向java.lang.Class集合的指针。没有元数据压缩的开销减少了GC Root的扫描不再扫描虚拟机里面的已加载类的目录和其它的内部哈希表G1回收器中并发标记阶段完成后就可以进行类的卸载元空间内存分配模型绝大多数的类元数据的空间都从本地内存中分配用来描述类元数据的对象也被移除为元数据分配了多个映射的虚拟内存空间。为每个类加载器分配一个内存块列表。 块的大小取决于类加载器的类型Java反射的字节码存取器sun.reflect.DelegatingClassLoader 占用内存更小空闲块内存返还给块内存列表当元空间为空虚拟内存空间会被回收减少了内存碎片异常 在JVM规范的描述中除了程序计数器以外虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError的可能。运行时区域异常主要原因 虚拟机栈和本地方法栈 StackOverflowError、OutOfMemoryError StackOverflowError线程请求的栈深度大于虚拟机所允许的最大深度OutOfMemoryError虚拟机在扩展栈时无法申请足够的内存空间 。  堆 OutOfMemoryError 对象数量到达最大堆的容量内存泄漏、内存溢出 方法区和运行时常量池 OutOfMemoryError 反射动态代理CGLib、JSP、OSGI等 内存泄露Memory Leak程序在申请内存后对象没有被GC所回收它始终占用内存内存泄漏的堆积最终会造成内存溢出。内存溢出Memory Overflow程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后仍然无内存空间容纳新的Java对象的情况。通常都是由于内存泄露导致堆栈内存不断增大从而引发内存溢出。