西安专业的网站优化,gom传奇网站建设,wordpress回复下载,3d建模培训班有用吗JVM 运行时内存区域划分是怎样的#xff1f; 程序计数器#xff1a;记录当前线程执行的字节码指令的地址#xff0c;是线程私有的。 Java 虚拟机栈#xff1a;每个方法在执行时都会创建一个栈帧#xff0c;用于存储局部变量表、操作数栈、动态链接、方法出口等信息#… JVM 运行时内存区域划分是怎样的 程序计数器记录当前线程执行的字节码指令的地址是线程私有的。 Java 虚拟机栈每个方法在执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息是线程私有的。 本地方法栈与 Java 虚拟机栈类似用于执行本地方法是线程私有的。 堆用于存储对象实例是线程共享的。 方法区用于存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据是线程共享的。在 JDK 1.8 中方法区被元空间Metaspace取代元空间使用本地内存。 常见的 GC 回收算法及其含义是什么 标记 - 清除算法分为标记和清除两个阶段。标记阶段标记出所有需要回收的对象清除阶段回收被标记的对象所占用的空间。该算法会产生大量的内存碎片。 复制算法将内存分为大小相等的两块每次只使用其中一块。当这块内存满了时将存活的对象复制到另一块内存中然后清除原来的内存。该算法不会产生内存碎片但会浪费一半的内存空间。 标记 - 整理算法在标记 - 清除算法的基础上增加了整理的步骤。在标记阶段标记出所有需要回收的对象清除阶段将存活的对象向一端移动然后清除边界以外的内存解决了内存碎片的问题。 分代收集算法根据对象的存活周期将内存划分为新生代和老年代。新生代采用复制算法老年代采用标记 - 清除或标记 - 整理算法。 什么是类加载器
类加载器是负责将字节码文件加载到 JVM 中并将其转换为 Class 对象的组件。Java 中有三种类型的类加载器 启动类加载器Bootstrap ClassLoader负责加载 Java 核心类库如 rt.jar是用 C 实现的无法被 Java 程序直接引用。 扩展类加载器Extension ClassLoader负责加载 Java 的扩展类库如 jre/lib/ext 目录下的类库。 应用程序类加载器Application ClassLoader负责加载应用程序的类如 classpath 下的类。 什么是双亲委派模型机制
当一个类加载器收到类加载请求时它首先不会自己去尝试加载这个类而是把请求委派给父类加载器去完成每一个层次的类加载器都是如此因此所有的加载请求最终都应该传送到顶层的启动类加载器中只有当父类加载器反馈自己无法完成这个加载请求它的搜索范围中没有找到所需的类时子类加载器才会尝试自己去加载。 一个类的生命周期是怎样的类是如何加载到 JVM 中的 生命周期加载、验证、准备、解析、初始化、使用、卸载。 加载过程 加载通过类加载器将字节码文件加载到内存中生成一个 Class 对象。 验证验证字节码文件的正确性确保其符合 Java 虚拟机规范包括文件格式验证、元数据验证、字节码验证和符号引用验证等步骤防止恶意字节码对 JVM 造成危害。 准备为类的静态变量分配内存并设置默认初始值如为整型变量赋 0引用类型赋 null 。 解析将常量池中的符号引用替换为直接引用也就是把类、接口、字段和方法的符号引用转换为具体内存地址的直接引用便于在运行时快速定位和访问这些元素。 初始化执行类构造器clinit()方法对静态变量进行显式赋值和执行静态代码块中的代码。clinit()方法是由编译器自动收集类中的所有静态变量的赋值动作和静态代码块中的语句合并产生的并且在多线程环境下JVM 会确保clinit()方法的线程安全性一个类的clinit()方法在多线程环境下只会被执行一次。 说说类加载的过程
类加载过程包含上述生命周期中的加载、验证、准备、解析、初始化这几个阶段加载阶段通过类加载器查找并读取字节码文件将其转化为内存中的 Class 对象验证阶段全方位检查字节码的合法性和安全性准备阶段为静态变量分配内存并赋予初始默认值解析阶段将常量池中的符号引用替换为直接引用初始化阶段执行clinit()方法完成静态变量的显式赋值和静态代码块的执行。例如当我们首次使用一个自定义类时JVM 会按照这个顺序逐步完成类的加载确保类在使用前已经被正确加载和初始化。 什么是强引用、软引用、弱引用、虚引用 强引用最常见的引用类型通过new关键字创建对象时就是强引用。只要强引用存在垃圾回收器就不会回收被引用的对象。例如Object obj new Object();只要obj引用存在对应的Object对象就不会被回收哪怕内存不足也不会回收可能导致 OOM。 软引用通过SoftReference类实现在内存充足时不会被回收当内存不足时会被回收。常用于实现内存敏感的缓存比如缓存图片等大对象在内存不够时系统会优先回收这些软引用指向的对象避免 OOM。 弱引用通过WeakReference类实现无论内存是否充足只要垃圾回收器扫描到就会回收被弱引用指向的对象。常用于解决内存泄漏问题例如在HashMap中如果使用强引用作为key当key不再使用但仍被HashMap引用时可能导致内存泄漏而使用弱引用作为key在key不再被其他地方引用时垃圾回收器会回收它避免内存泄漏。 虚引用通过PhantomReference类实现也叫幻影引用它对对象的生命周期没有影响无法通过虚引用来获取对象实例主要用于在对象被回收时收到一个系统通知例如用于管理堆外内存资源当对象被回收时可通过虚引用关联的引用队列来触发堆外内存的释放操作。 Minor GC 与 Full GC 分别在什么时候发生 Minor GC发生在新生代当新生代的 Eden 区满了无法存放新创建的对象时就会触发 Minor GC。它会回收新生代中不再被引用的对象由于新生代对象大多 “朝生夕灭”所以 Minor GC 的频率较高但回收速度相对较快。 Full GC发生在老年代常见的触发场景有老年代空间不足、方法区空间不足、显式调用System.gc() 不过System.gc()只是建议 JVM 进行 Full GCJVM 不一定会立即执行、大对象直接进入老年代且老年代空间不够时以及在进行 Minor GC 时动态年龄判断发现 Survivor 区中相同年龄所有对象大小的总和大于 Survivor 空间的一半年龄大于或等于该年龄的对象就可以直接进入老年代若老年代空间不足就会触发 Full GC。Full GC 会对整个堆包括新生代和老年代和方法区进行垃圾回收回收速度相对较慢因为老年代中的对象存活时间长垃圾回收的成本更高。 什么时候触发 Full GC
除了上述提到的老年代空间不足、方法区空间不足、显式调用System.gc() 、大对象直接进入老年代且老年代空间不够、Minor GC 时动态年龄判断导致老年代空间不足等情况外还有以下情况当 JVM 的堆内存使用率达到一定阈值可通过参数设置如-XX:HeapDumpOnOutOfMemoryError 结合-XX:OnOutOfMemoryError 等参数配合监控和触发相关操作可能会触发 Full GC在使用 CMSConcurrent Mark Sweep垃圾回收器时如果在并发标记和清理阶段出现 Concurrent Mode Failure即 CMS 在垃圾回收过程中应用程序又产生了大量垃圾导致老年代剩余空间无法容纳新的垃圾对象也会触发 Full GC。 Java 中的大对象如何进行存储
大对象通常指需要大量连续内存空间的对象如大数组。在 Java 中大对象一般会直接分配到老年代。因为新生代的空间相对较小且使用复制算法频繁地在新生代分配和回收大对象可能会导致大量的内存复制操作影响性能。而老年代空间较大并且采用标记 - 清除或标记 - 整理算法更适合存储大对象。不过当老年代空间不足时就可能触发 Full GC 来回收老年代空间以容纳大对象。此外可以通过调整 JVM 参数如-XX:PretenureSizeThreshold 来设置大对象直接进入老年代的阈值当对象大小超过该阈值时就直接在老年代分配内存。 为什么新生代内存需要有两个 Survivor 区
新生代采用复制算法进行垃圾回收两个 Survivor 区一般称为 From Survivor 和 To Survivor的设计是为了实现高效的垃圾回收。在每次 Minor GC 时Eden 区和 From Survivor 区中存活的对象会被复制到 To Survivor 区然后清空 Eden 区和 From Survivor 区。下次 Minor GC 时From Survivor 区和 To Survivor 区的角色互换即原来的 To Survivor 区变为 From Survivor 区原来的 From Survivor 区变为 To Survivor 区。这样设计的好处是一方面避免了像标记 - 清除算法那样产生内存碎片另一方面通过复制存活对象使得存活时间长的对象逐步晋升到老年代因为每次复制时对象的年龄在 Survivor 区经历一次 Minor GC年龄就加 1会增加当年龄达到一定阈值默认为 15时对象就会被晋升到老年代从而保证新生代的空间能够高效地利用提高垃圾回收的效率。