网站字体设计重要性wordpress whatnew
2026/4/2 5:42:34 网站建设 项目流程
网站字体设计重要性,wordpress whatnew,山东东营网络seo,做十个网站1、JVM中线程私有的和线程共享的分别是 线程私有的有#xff1a;栈、本地方法栈、程序计数器 线程共享的有#xff1a;方法区、直接内存、堆 2、️哪个区域不会出现 OutOfMemoryError#xff1f; 程序计数器是唯一一个不会出现 OutOfMemoryError 的内存区域#xff0c;它的…1、JVM中线程私有的和线程共享的分别是线程私有的有栈、本地方法栈、程序计数器线程共享的有方法区、直接内存、堆2、️哪个区域不会出现 OutOfMemoryError程序计数器是唯一一个不会出现 OutOfMemoryError 的内存区域它的生命周期随着线程的创建而创建随着线程的结束而死亡。程序计数器是一块较小的内存空间可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时通过改变这个计数器的值来选取下一条需要执行的字节码指令分支、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器来完成。另外为了线程切换后能恢复到正确的执行位置每条线程都需要有一个独立的程序计数器各线程之间计数器互不影响独立存储我们称这类内存区域为“线程私有”的内存。从上面的介绍中我们知道了程序计数器主要有两个作用字节码解释器通过改变程序计数器来依次读取指令从而实现代码的流程控制如顺序执行、选择、循环、异常处理。在多线程的情况下程序计数器用于记录当前线程执行的位置从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。3、哪些情况可能会出现堆溢出堆溢出也就是我们常说的OutOfMemoryError: Java heap space是 Java 开发中非常常见的一种严重错误。它的根本原因就是 JVM 在尝试为新对象分配内存时堆中已经没有足够的连续空间了并且经过垃圾回收后也无法腾出足够的空间。导致堆溢出的场景主要可以分为两类内存泄漏对象用完了但没被释放比如static集合无限增长、ThreadLocal没调用remove()。内存膨胀短时间内创建了太多对象比如一次性从数据库查了几百万条数据到 List 里或者直接把一个大文件整个读进内存。4、程序运行时栈可能出现的错误**StackOverFlowError**如果栈的内存大小不允许动态扩展那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度的时候就抛出StackOverFlowError错误。**OutOfMemoryError**如果栈的内存大小可以动态扩展 那么当虚拟机在动态扩展栈时无法申请到足够的内存空间则抛出OutOfMemoryError异常。5、堆的作用和组成Java 虚拟机所管理的内存中最大的一块Java 堆是所有线程共享的一块内存区域在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例几乎所有的对象实例以及数组都在这里分配内存。Java 堆是垃圾收集器管理的主要区域因此也被称作GC 堆Garbage Collected Heap。从垃圾回收的角度由于现在收集器基本都采用分代垃圾收集算法所以 Java 堆还可以细分为新生代和老年代再细致一点有Eden、Survivor、Old 等空间。进一步划分的目的是更好地回收内存或者更快地分配内存。在 JDK 7 版本及 JDK 7 版本之前堆内存被通常分为下面三部分新生代内存(Young Generation)老生代(Old Generation)永久代(Permanent Generation)JDK 8 版本之后 PermGen(永久代) 已被 Metaspace(元空间) 取代元空间使用的是本地内存。我会在方法区这部分内容详细介绍到。大部分情况对象都会首先在 Eden 区域分配在一次新生代垃圾回收后如果对象还存活则会进入 S0 或者 S1并且对象的年龄还会加 1(Eden 区-Survivor 区后对象的初始年龄变为 1)当它的年龄增加到一定程度默认为 15 岁就会被晋升到老年代中。对象晋升到老年代的年龄阈值可以通过参数-XX:MaxTenuringThreshold来设置。不过设置的值应该在 0-15否则会爆出以下错误MaxTenuringThreshold of20is invalid;must be between0and156、为什么说基本上所有对象都在堆中创建而不是所有对象都在堆上创建因为栈上分配经过逃逸分析之后如果为非逃逸对象则会被分配到栈中随着站的销毁而销毁。7、方法区常见的参数有JDK 1.8 之前永久代还没被彻底移除的时候通常通过下面这些参数来调节方法区大小。-XX:PermSizeN//方法区 (永久代) 初始大小-XX:MaxPermSizeN//方法区 (永久代) 最大大小,超过这个值将会抛出 OutOfMemoryError 异常:java.lang.OutOfMemoryError: PermGen相对而言垃圾收集行为在这个区域是比较少出现的但并非数据进入方法区后就“永久存在”了。JDK 1.8 的时候方法区HotSpot 的永久代被彻底移除了JDK1.7 就已经开始了取而代之是元空间元空间使用的是本地内存。下面是一些常用参数-XX:MetaspaceSizeN//设置 Metaspace 的初始和最小大小-XX:MaxMetaspaceSizeN//设置 Metaspace 的最大大小与永久代很大的不同就是如果不指定大小的话随着更多类的创建虚拟机会耗尽所有可用的系统内存。8、字符常量池的作用字符串常量池是 JVM 为了提升性能和减少内存消耗针对字符串String 类专门开辟的一块区域主要目的是为了避免字符串的重复创建。// 在字符串常量池中创建字符串对象 ”ab“// 将字符串对象 ”ab“ 的引用赋值给给 aaStringaaab;// 直接返回字符串常量池中字符串对象 ”ab“赋值给引用 bbStringbbab;System.out.println(aabb);// trueHotSpot 虚拟机中字符串常量池的实现是src/hotspot/share/classfile/stringTable.cpp,StringTable可以简单理解为一个固定大小的HashTable容量为StringTableSize可以通过-XX:StringTableSize参数来设置保存的是字符串key和 字符串对象的引用value的映射关系字符串对象的引用指向堆中的字符串对象。JDK1.7 之前字符串常量池存放在永久代。JDK1.7 字符串常量池和静态变量从永久代移动到了 Java 堆中。9、JDK 1.7 为什么要将字符串常量池移动到堆中主要是因为永久代方法区实现的 GC 回收效率太低只有在整堆收集 (Full GC)的时候才会被执行 GC。Java 程序中通常会有大量的被创建的字符串等待回收将字符串常量池放到堆中能够更高效及时地回收字符串内存。10、对象访问定位的方式有哪些建立对象就是为了使用对象我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定目前主流的访问方式有使用句柄、直接指针。句柄如果使用句柄的话那么 Java 堆中将会划分出一块内存来作为句柄池reference 中存储的就是对象的句柄地址而句柄中包含了对象实例数据与对象类型数据各自的具体地址信息。直接指针如果使用直接指针访问reference 中存储的直接就是对象的地址。这两种对象访问方式各有优势。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址在对象被移动时只会改变句柄中的实例数据指针而 reference 本身不需要修改。使用直接指针访问方式最大的好处就是速度快它节省了一次指针定位的时间开销。HotSpot 虚拟机主要使用的就是这种方式来进行对象访问。11、如何判断对象是否死亡堆中几乎放着所有的对象实例对堆垃圾回收前的第一步就是要判断哪些对象已经死亡即不能再被任何途径使用的对象。引用计数法给对象中添加一个引用计数器每当有一个地方引用它计数器就加 1当引用失效计数器就减 1任何时候计数器为 0 的对象就是不可能再被使用的。这个**方法实现简单效率高但是目前主流的虚拟机中并没有选择这个算法来管理内存其最主要的原因是它很难解决对象之间循环引用的问题。**所谓对象之间的相互引用问题如下面代码所示除了对象objA和objB相互引用着对方之外这两个对象之间再无任何引用。但是他们因为互相引用对方导致它们的引用计数器都不为 0于是引用计数算法无法通知 GC 回收器回收他们。publicclassReferenceCountingGc{Objectinstancenull;publicstaticvoidmain(String[]args){ReferenceCountingGcobjAnewReferenceCountingGc();ReferenceCountingGcobjBnewReferenceCountingGc();objA.instanceobjB;objB.instanceobjA;objAnull;objBnull;}}可达性分析算法这个算法的基本思想就是通过一系列的称为“GC Roots”的对象作为起点从这些节点开始向下搜索节点所走过的路径称为引用链当一个对象到 GC Roots 没有任何引用链相连的话则证明此对象是不可用的需要被回收。下图中的Object 6 ~ Object 10之间虽有引用关系但它们到 GC Roots 不可达因此为需要被回收的对象。哪些对象可以作为 GC Roots 呢虚拟机栈(栈帧中的局部变量表)中引用的对象本地方法栈(Native 方法)中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象所有被同步锁持有的对象JNIJava Native Interface引用的对象对象可以被回收就代表一定会被回收吗即使在可达性分析法中不可达的对象也并非是“非死不可”的这时候它们暂时处于“缓刑阶段”要真正宣告一个对象死亡至少要经历两次标记过程可达性分析法中不可达的对象被第一次标记并且进行一次筛选筛选的条件是此对象是否有必要执行finalize方法。当对象没有覆盖finalize方法或finalize方法已经被虚拟机调用过时虚拟机将这两种情况视为没有必要执行。被判定为需要执行的对象将会被放在一个队列中进行第二次标记除非这个对象与引用链上的任何一个对象建立关联否则就会被真的回收。12、常见的引用类型有哪些无论是通过引用计数法判断对象引用数量还是通过可达性分析法判断对象的引用链是否可达判定对象的存活都与“引用”有关。JDK1.2 之前Java 中引用的定义很传统如果 reference 类型的数据存储的数值代表的是另一块内存的起始地址就称这块内存代表一个引用。JDK1.2 以后Java 对引用的概念进行了扩充将引用分为强引用、软引用、弱引用、虚引用四种引用强度逐渐减弱强引用就是 Java 中普通的对象而软引用、弱引用、虚引用在 JDK 中定义的类分别是 SoftReference、WeakReference、PhantomReference。1强引用StrongReference强引用实际上就是程序代码中普遍存在的引用赋值这是使用最普遍的引用其代码如下StringstrongReferencenewString(abc);如果一个对象具有强引用那就类似于必不可少的生活用品垃圾回收器绝不会回收它。当内存空间不足Java 虚拟机宁愿抛出 OutOfMemoryError 错误使程序异常终止也不会靠随意回收具有强引用的对象来解决内存不足问题。2软引用SoftReference如果一个对象只具有软引用那就类似于可有可无的生活用品。软引用代码如下// 软引用StringstrnewString(abc);SoftReferenceStringsoftReferencenewSoftReferenceString(str);如果内存空间足够垃圾回收器就不会回收它如果内存空间不足了就会回收这些对象的内存。只要垃圾回收器没有回收它该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列ReferenceQueue联合使用如果软引用所引用的对象被垃圾回收JAVA 虚拟机就会把这个软引用加入到与之关联的引用队列中。3弱引用WeakReference如果一个对象只具有弱引用那就类似于可有可无的生活用品。弱引用代码如下StringstrnewString(abc);WeakReferenceStringweakReferencenewWeakReference(str);strnull;//str变成软引用可以被收集弱引用与软引用的区别在于只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中一旦发现了只具有弱引用的对象不管当前内存空间足够与否都会回收它的内存。不过由于垃圾回收器是一个优先级很低的线程 因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列ReferenceQueue联合使用如果弱引用所引用的对象被垃圾回收Java 虚拟机就会把这个弱引用加入到与之关联的引用队列中。4虚引用PhantomReference虚引用顾名思义就是形同虚设与其他几种引用都不同虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用那么它就和没有任何引用一样在任何时候都可能被垃圾回收。虚引用代码如下StringstrnewString(abc);ReferenceQueuequeuenewReferenceQueue();// 创建虚引用要求必须与一个引用队列关联PhantomReferenceprnewPhantomReference(str,queue);虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于虚引用必须和引用队列ReferenceQueue联合使用。当垃圾回收器准备回收一个对象时如果发现它还有虚引用就会在回收对象的内存之前把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列那么就可以在所引用的对象的内存被回收之前采取必要的行动。特别注意在程序设计中一般很少使用弱引用与虚引用使用软引用的情况较多这是因为软引用可以加速 JVM 对垃圾内存的回收速度可以维护系统的运行安全防止内存溢出OutOfMemory等问题的产生。13、如何判断类是一个无用的类该类所有的实例都已经被回收也就是 Java 堆中不存在该类的任何实例。加载该类的ClassLoader已经被回收。该类对应的java.lang.Class对象没有在任何地方被引用无法在任何地方通过反射访问该类的方法。14、垃圾回收算法有哪些标记-清除算法标记-清除Mark-and-Sweep算法分为“标记Mark”和“清除Sweep”阶段首先标记出所有不需要回收的对象在标记完成后统一回收掉所有没有被标记的对象。它是最基础的收集算法后续的算法都是对其不足进行改进得到。这种垃圾收集算法会带来两个明显的问题效率问题标记和清除两个过程效率都不高。空间问题标记清除后会产生大量不连续的内存碎片。当一个对象被创建时给一个标记位假设为 0 (false)在标记阶段我们将所有可达对象或用户可以引用的对象的标记位设置为 1 (true)扫描阶段清除的就是标记位为 0 (false)的对象。复制算法为了解决标记-清除算法的效率和内存碎片问题复制Copying收集算法出现了。它可以将内存分为大小相同的两块每次使用其中的一块。当这一块的内存使用完后就将还存活的对象复制到另一块去然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。虽然改进了标记-清除算法但依然存在下面这些问题可用内存变小可用内存缩小为原来的一半。不适合老年代如果存活对象数量比较大复制性能会变得很差。标记-整理算法标记-整理Mark-and-Compact算法是根据老年代的特点提出的一种标记算法标记过程仍然与“标记-清除”算法一样但后续步骤不是直接对可回收对象回收而是让所有存活的对象向一端移动然后直接清理掉端边界以外的内存。由于多了整理这一步因此效率也不高适合老年代这种垃圾回收频率不是很高的场景。分代收集方法当前虚拟机的垃圾收集都采用分代收集算法这种算法没有什么新的思想只是根据对象存活周期的不同将内存分为几块。一般将 Java 堆分为新生代和老年代这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中每次收集都会有大量对象死去所以可以选择”标记-复制“算法只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的而且没有额外的空间对它进行分配担保所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。15、JDK 1.8 的默认垃圾回收器是JDK1.9 之后呢JDK 1.8 默认垃圾回收器Parallel Scanvenge新生代 Parallel Old老年代。 这个组合也被称为 Parallel GC 或 Throughput GC侧重于吞吐量。JDK 1.9 及以后默认垃圾回收器G1 GC (Garbage-First Garbage Collector)。 G1 GC 是一个更现代化的垃圾回收器旨在平衡吞吐量和停顿时间尤其适用于堆内存较大的应用。16、G1 垃圾回收的过程G1Garbage-First垃圾收集器在 JDK 7 中首次引入作为一种试验性的垃圾收集器。到了 JDK 8G1 得到了进一步的完善和改进功能基本已经完全实现成为一个稳定、可用于生产环境的垃圾收集器。G1 收集器的运作大致分为以下几个步骤初始标记 短暂停顿Stop-The-WorldSTW标记从 GC Roots 可直接引用的对象即标记所有直接可达的活跃对象并发标记与应用并发运行标记所有可达对象。 这一阶段可能持续较长时间取决于堆的大小和对象的数量。最终标记 短暂停顿STW处理并发标记阶段结束后残留的少量未处理的引用变更。筛选回收根据标记结果选择回收价值高的区域复制存活对象到新区域回收旧区域内存。这一阶段包含一个或多个停顿STW具体取决于回收的复杂度。G1 收集器在后台维护了一个优先列表每次根据允许的收集时间优先选择回收价值最大的 Region(这也就是它的名字 Garbage-First 的由来)。这种使用 Region 划分内存空间以及有优先级的区域回收方式保证了 G1 收集器在有限时间内可以尽可能高的收集效率把内存化整为零。17、ZGC的改进是什么与 CMS、ParNew 和 G1 类似ZGC 也采用标记-复制算法不过 ZGC 对该算法做了重大改进。ZGC 可以将暂停时间控制在几毫秒以内且暂停时间不受堆内存大小的影响出现 Stop The World 的情况会更少但代价是牺牲了一些吞吐量。ZGC 最大支持 16TB 的堆内存。ZGC 在 Java11 中引入处于试验阶段。经过多个版本的迭代不断的完善和修复问题ZGC 在 Java15 已经可以正式使用了。不过默认的垃圾回收器依然是 G1。你可以通过下面的参数启用 ZGCjava-XX:UseZGCclassName在 Java21 中引入了分代 ZGC暂停时间可以缩短到 1 毫秒以内。你可以通过下面的参数启用分代 ZGCjava-XX:UseZGC-XX:ZGenerationalclassName18、双亲委派模型双亲委派模型是什么类加载器有很多种当我们想要加载一个类的时候具体是哪个类加载器加载呢这就需要提到双亲委派模型了。ClassLoade 类使用委托模型来搜索类和资源。每个 ClassLoader实例都有一个相关的父类加载器。需要查找类或资源时ClassLoader 实例会在试图亲自查找类或资源之前将搜索类或资源的任务委托给其父类加载器。虚拟机中被称为 bootstrap class loader的内置类加载器本身没有父类加载器但是可以作为 ClassLoader 实例的父类加载器。ClassLoader 类使用委托模型来搜索类和资源。双亲委派模型要求除了顶层的启动类加载器外其余的类加载器都应有自己的父类加载器。ClassLoader 实例会在试图亲自查找类或资源之前将搜索类或资源的任务委托给其父类加载器。注意 ⚠️双亲委派模型并不是一种强制性的约束只是 JDK 官方推荐的一种方式。如果我们因为某些特殊需求想要打破双亲委派模型也是可以的。19、JVM的内存模型介绍一下根据 JDK 8 规范JVM 运行时内存共分为虚拟机栈、堆、元空间、程序计数器、本地方法栈五个部分。还有一部分内存叫直接内存属于操作系统的本地内存也是可以直接操作的。程序计数器可以看作是当前线程所执行的字节码的行号指示器用于存储当前线程正在执行的 Java 方法的 JVM 指令地址。如果线程执行的是 Native 方法计数器值为 null。是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域生命周期与线程相同。Java 虚拟机栈每个线程都有自己独立的 Java 虚拟机栈生命周期与线程相同。每个方法在执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。可能会抛出 StackOverflowError 和 OutOfMemoryError 异常。本地方法栈与 Java 虚拟机栈类似主要为虚拟机使用到的 Native 方法服务在 HotSpot 虚拟机中和 Java 虚拟机栈合二为一。本地方法执行时也会创建栈帧同样可能出现 StackOverflowError 和 OutOfMemoryError 两种错误。Java 堆是 JVM 中最大的一块内存区域被所有线程共享在虚拟机启动时创建用于存放对象实例。从内存回收角度堆被划分为新生代和老年代新生代又分为 Eden 区和两个 Survivor 区From Survivor 和 To Survivor。如果在堆中没有内存完成实例分配并且堆也无法扩展时会抛出 OutOfMemoryError 异常。方法区元空间在 JDK 1.8 及以后的版本中方法区被元空间取代使用本地内存。用于存储已被虚拟机加载的类信息、常量、静态变量等数据。虽然方法区被描述为堆的逻辑部分但有 “非堆” 的别名。方法区可以选择不实现垃圾收集内存不足时会抛出 OutOfMemoryError 异常。运行时常量池是方法区的一部分用于存放编译期生成的各种字面量和符号引用具有动态性运行时也可将新的常量放入池中。当无法申请到足够内存时会抛出 OutOfMemoryError 异常。直接内存不属于 JVM 运行时数据区的一部分通过 NIO 类引入是一种堆外内存可以显著提高 I/O 性能。直接内存的使用受到本机总内存的限制若分配不当可能导致 OutOfMemoryError 异常。20、JVM中堆和栈的区别以下是将你提供的内容解析整理后的清晰 Markdown 格式完整保留核心信息且排版更易读用途栈主要用于存储局部变量、方法调用的参数、方法返回地址以及一些临时数据。每当一个方法被调用一个栈帧stack frame就会在栈中创建用于存储该方法的信息当方法执行完毕栈帧也会被移除。堆用于存储对象的实例包括类的实例和数组。当你使用new关键字创建一个对象时对象的实例就会在堆上分配空间。生命周期栈中的数据具有确定的生命周期当一个方法调用结束时其对应的栈帧就会被销毁栈中存储的局部变量也会随之消失。堆中的对象生命周期不确定对象会在垃圾回收机制Garbage Collection, GC检测到对象不再被引用时才被回收。存取速度栈的存取速度通常比堆快因为栈遵循先进后出LIFO, Last In First Out的原则操作简单快速。堆的存取速度相对较慢因为对象在堆上的分配和回收需要更多的时间而且垃圾回收机制的运行也会影响性能。存储空间栈的空间相对较小且固定由操作系统管理。当栈溢出时通常是因为递归过深或局部变量过大。堆的空间较大动态扩展由JVM管理。堆溢出通常是由于创建了太多的大对象或未能及时回收不再使用的对象。可见性栈中的数据对线程是私有的每个线程有自己的栈空间。堆中的数据对线程是共享的所有线程都可以访问堆上的对象。21、栈中存的到底是指针还是对象对于引用类型栈中存的是指针/引用对象的堆内存地址对于基本类型栈中直接存值对象本身永远在堆上除非栈上分配优化22、方法区有什么东西类信息包括类的结构信息、类的访问修饰符、父类与接口等信息。常量池存储类和接口中的常量包括字面值常量、符号引用以及运行时常量池。静态变量存储类的静态变量这些变量在类初始化的时候被赋值。方法字节码存储类的方法字节码即编译后的代码。符号引用存储类和方法的符号引用是一种与直接引用不同的引用类型。运行时常量池存储着在类文件中的常量池数据在类加载后在方法区生成该运行时常量池。常量池缓存用于提升类加载的效率将常用的常量缓存起来方便使用。23、jvm 内存结构有哪几种内存溢出的情况堆内存溢出当出现Java.lang.OutOfMemoryError: Java heap space异常时就是堆内存溢出了。原因是代码中可能存在大对象分配或者发生了内存泄露导致在多次 GC 之后还是无法找到一块足够大的内存容纳当前对象。栈溢出如果我们写一段程序不断地进行递归调用而且没有退出条件就会导致不断地进行压栈。类似这种情况JVM 实际会抛出StackOverFlowError当然如果 JVM 试图去扩展栈空间的时候失败则会抛出OutOfMemoryError。元空间溢出元空间的溢出系统会抛出Java.lang.OutOfMemoryError: Metaspace。出现这个异常的原因是系统的代码非常多、引用的第三方包非常多或者通过动态代码生成类加载等方法导致元空间的内存占用很大。直接内存溢出在使用ByteBuffer中的allocateDirect()的时候会用到直接内存很多 Java NIO像 netty的框架中该方法被封装为其他的方法出现该问题时会抛出Java.lang.OutOfMemoryError: Direct buffer memory异常。24、栈溢出的情况呢java.lang.StackOverflowError栈溢出是 JVM 中另一种常见的内存错误和堆溢出的原理与场景截然不同。栈溢出主要发生在 Java 虚拟机栈或本地方法栈的内存空间被耗尽时通常与方法调用的深度直接相关。从触发原因来看最常见的场景是无限递归调用。因为 Java 方法调用时会在栈中创建栈帧存储局部变量、操作数栈、方法返回地址等每递归一次就会新增一个栈帧。如果递归没有正确的终止条件栈帧会不断累积最终超过虚拟机栈的最大容量导致栈溢出。比如一个简单的无终止条件的递归方法public void test1(){ test1() }解决栈溢出的方式排查递归逻辑检查是否存在无限递归或递归层级过深的问题添加正确的终止条件或减少递归深度。必要时可将递归改写为迭代如用循环替代因为迭代不会持续创建新栈帧。调整栈内存大小通过 JVM 参数-Xss如-Xss256k增大栈内存容量。但这种方式要谨慎栈内存过大会导致线程可创建数量减少总内存固定时单个线程栈越大能创建的线程数越少。优化方法栈帧减少方法内局部变量的数量避免在方法中创建过大的对象或数组将大对象的创建移到堆中通过 new 关键字降低单个栈帧的内存占用。25、垃圾回收器有哪些

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询