给人做网站多少钱,织梦网站怎么做备份,济南软件外包,网站开发 验收模板一、运行时数据区域
堆、方法区#xff08;元空间#xff09;、虚拟机栈、本地方法栈、程序计数器。 Heap(堆)#xff1a;
对象的实例以及数组的内存都是要在堆上进行分配的#xff0c;堆是线程共享的一块区域#xff0c;用来存放对象实例#xff0c;也是垃圾回收…一、运行时数据区域
堆、方法区元空间、虚拟机栈、本地方法栈、程序计数器。 Heap(堆)
对象的实例以及数组的内存都是要在堆上进行分配的堆是线程共享的一块区域用来存放对象实例也是垃圾回收GC的主要区域开启逃逸分析后某些未逃逸的对象可以通过标量替换的方式在栈中分配。
堆细分新生代、老年代对于新生代又分为Eden区和Surviver1和Surviver2区。
方法区
对于JVM的方法区也可以称之为永久区它储存的是已经被java虚拟机加载的类信息、常量、静态变量Jdk1.8以后取消了方法区这个概念称之为元空间MetaSpace
当应用中的 Java 类过多时比如 Spring 等一些使用动态代理的框架生成了很多类如果占用空间超出了我们的设定值就会发生元空间溢出。
虚拟机栈
虚拟机栈是线程私有的他的生命周期和线程的生命周期是一致的。里面装的是一个一个的栈帧每一个方法在执行的时候都会创建一个栈帧栈帧中用来存放局部变量表、操作数栈 、动态链接 、返回地址在Java虚拟机规范中对此区域规定了两种异常状况如果线程请求的栈深度大于虚拟机所允许的深度将会抛出StackOverflowError异常如果虚拟机栈动态扩展时无法申请到足够的内存就会抛出OutOfMemoryError异常。 局部变量表局部变量表是一组变量值存储空间用来存放方法参数、方法内部定义的局部变量。底层是变量槽variable slot 操作数栈是用来记录一个方法在执行的过程中字节码指令向操作数栈中进行入栈和出栈的过程。大小在编译的时候已经确定了当一个方法刚开始执行的时候操作数栈中是空发的在方法执行的过程中会有各种字节码指令往操作数栈中入栈和出栈。 动态链接因为字节码文件中有很多符号的引用这些符号引用一部分会在类加载的解析阶段或第一次使用的时候转化成直接引用这种称为静态解析另一部分会在运行期间转化为直接引用称为动态链接。 返回地址returnAddress类型指向了一条字节码指令的地址 JIT即时编译器Just In Time Compiler简称 JIT 编译器: 为了提高热点代码的执行效率在运行时虚拟机将会把这些代码编译成与本地平台相关的机器码并进行各种层次的优化比如锁粗化等。
本地方法栈
本地方法栈和虚拟机栈类似不同的是虚拟机栈服务的是Java方法而本地方法栈服务的是Native方法。在HotSpot虚拟机实现中是把本地方法栈和虚拟机栈合二为一的同理它也会抛出StackOverflowError和OOM异常。
PC程序计数器
PC指的是存放下一条指令的位置的一个指针。它是一块较小的内存空间且是线程私有的。由于线程的切换CPU在执行的过程中需要记住原线程的下一条指令的位置所以每一个线程都需要有自己的PC。
二、堆内存分配策略 对象优先分配在Eden区如果Eden区没有足够的空间进行分配时虚拟机执行一次MinorGC。而那些无需回收的存活对象将会进到 Survivor 的 From 区From 区内存不足时直接进入 Old 区。 大对象直接进入老年代需要大量连续内存空间的对象。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝新生代采用复制算法收集内存。 长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄Age Count计数器如果对象经过了1次Minor GC那么对象会进入Survivor区之后每经过一次Minor GC那么对象的年龄加1直到达到阀值默认15次对象进入老年区。 动态对象年龄判定程序从年龄最小的对象开始累加如果累加的对象大小大于幸存区的一半则将当前的对象 age 作为新的阈值年龄大于此阈值的对象则直接进入老年代。 每次进行Minor GC或者大对象直接进入老年区时JVM会计算所需空间大小如小于老年区的剩余值大小则进行一次Full GC。 三、创建一个对象的步骤
步骤类加载检查、分配内存、初始化零值、设置对象头、执行init方法
①类加载检查
虚拟机遇到 new 指令时⾸先去检查是否能在常量池中定位到这个类的符号引⽤并且检查这个符号引⽤代表的类是否已被加载过、解析和初始化过。如果没有那必须先执⾏相应的类加载过程。
②分配内存
在类加载检查通过后接下来虚拟机将为新⽣对象分配内存分配⽅式有 “指针碰撞” 和 “空闲列表” 两种选择那种分配⽅式由 Java 堆是否规整决定⽽Java堆是否规整⼜由所采⽤的垃圾收集器是否带有压缩整理功能决定。
③初始化零值
内存分配完成后虚拟机需要将分配到的内存空间都初始化为零值这⼀步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使⽤程序能访问到这些字段的数据类型所对应的零值。
④设置对象头
初始化零值完成之后虚拟机要对对象进⾏必要的设置例如这个对象是那个类的实例、如何才能找到类的元数据信息、对象的哈希吗、对象的 GC 分代年龄等信息。这些信息存放在对象头中。另外根据虚拟机当前运⾏状态的不同如是否启⽤偏向锁等对象头会有不同的设置⽅式。
⑤执⾏ init ⽅法
从虚拟机的视⻆来看⼀个新的对象已经产⽣了但从Java 程序的视⻆来看 ⽅法还没有执⾏所有的字段都还为零。所以⼀般来说除循环依赖执⾏ new 指令之后会接着执⾏ ⽅法这样⼀个真正可⽤的对象才算产⽣出来。
四、对象引用
普通的对象引用关系就是强引用。
软引用用于维护一些可有可无的对象。只有在内存不足时系统则会回收软引用对象如果回收了软引用对象之后仍然没有足够的内存才会抛出内存溢出异常。
弱引用对象相比软引用来说要更加无用一些它拥有更短的生命周期当 JVM 进行垃圾回收时无论内存是否充足都会回收被弱引用关联的对象。
虚引用是一种形同虚设的引用在现实场景中用的不是很多它主要用来跟踪对象被垃圾回收的活动。