JVM之垃圾回收
1. 如何判断对象可以回收
1.1 引用计数法
引用计数法是一种内存管理技术,其中每个对象都有一个与之关联的引用计数。引用计数表示当前有多少个指针引用了该对象。当引用计数变为零时,表示没有指针再指向该对象,该对象可以被释放,因为没有程序可以再访问它。
基本思想是在对象创建时初始化引用计数为1,每当有新的引用指向对象时,引用计数加1,当引用离开作用域或者被显式赋值为其他值时,引用计数减1。当引用计数为零时,释放对象的内存。
虽然引用计数法简单,但它有一些缺点,其中最主要的是不能解决循环引用的问题。如果两个或多个对象形成环状引用(彼此相互引用),它们的引用计数永远不会变为零,即使程序不再使用它们,这会导致内存泄漏。
1.2 可达性分析法
可达性分析是一种垃圾回收算法,用于确定在程序执行期间哪些对象是可访问的,即哪些对象可以被程序的根引用直接或间接访问到。这种算法通过从根引用出发,沿着对象之间的引用链,标记所有可达的对象,然后将未标记的对象认定为不可达,从而进行垃圾回收。
在可达性分析算法中,根对象是算法的起始点,从这些根对象开始追踪引用链以标记可达的对象。以下是一些典型的可达性分析算法的根对象:
-
虚拟机栈的本地变量引用的对象(Local Variables in Stack Frames):
属于当前线程的栈帧中的本地变量可以作为根对象。这包括方法的参数、局部变量等。
-
本地方法栈中的变量引用的对象
与虚拟机栈类似,但是用于支持本地方法(Native Method)的栈。 -
静态变量引用的对象(Static Variables):
静态变量属于类而不是实例,因此在整个程序运行期间都存在。静态变量可以作为根对象,因为它们在程序的整个生命周期中都能被访问到。
-
常量引用的对象(Constant References):
对于一些被认为是常量的引用,它们在整个程序运行期间都是可达的。这可能包括一些预定义的常量、静态 final 字段等。
-
活动的线程对象(Thread):
线程对象本身可以被视为根对象。每个线程通常都有一个栈,栈中的内容(如本地变量)可以作为可达性分析的根。
-
被同步锁持有的对象(Locked Objects):
被Java线程持有的同步锁的对象,因为这些对象可能在其他线程中被访问。
-
Java核心类库对象:
如java.lang.Class对象。
这些根对象通常是垃圾回收器开始遍历引用链的起点。通过从这些根对象开始,垃圾回收器可以识别并标记所有通过引用链可达的对象,并最终确定哪些对象是不可达的,从而进行垃圾回收。
可达性分析算法的优点之一是它可以处理循环引用,因为只要一组对象是可达的,它们就不会被回收。这种算法通常与分代垃圾回收结合使用,以更有效地管理不同生命周期的对象。
Java虚拟机中的垃圾回收器(如G1收集器)就使用了可达性分析算法。这种算法的一个关键优势是,在进行垃圾回收的同时,程序的其他部分仍然可以继续执行,从而减小了垃圾回收对程序性能的影响。
1.3 四种引用
-
强引用
强引用(Strong Reference)是Java中最普遍的引用类型。当一个对象具有强引用时,垃圾回收器不会回收这个对象,即使系统中存在内存不足的情况。只有当没有任何强引用指向一个对象时,该对象才会被垃圾回收器回收。
在Java中,一般的对象引用,如赋值操作 Object obj = new Object(); 就是强引用。例如:
Object obj = new Object(); // 强引用
在这个例子中,obj 引用了一个新创建的 Object 对象。只要 obj 不被重新赋值为其他值,这个 Object 对象就会一直存在,不会被垃圾回收。
强引用确保了对象的存在不会受到垃圾回收的影响,但也意味着程序员需要自己管理对象的生命周期,及时释放不再需要的引用,以便让垃圾回收器能够回收不再被引用的对象。
Object obj = new Object(); // 强引用 // 在某个时刻不再需要obj引用的对象 obj = null; // 将obj设置为null,释放对Object对象的强引用
上述操作后,如果没有其他引用指向这个 Object 对象,它就变得不可达,最终可能被垃圾回收器回收。强引用的使用非常普遍,但需要谨慎管理,以避免内存泄漏或者持续占用过多内存的问题。
-
软引用
软引用(Soft Reference)是Java中一种相对强引用更具弹性的引用类型。当一个对象只被软引用引用时,在内存不足时,这个对象可能被垃圾回收器回收,但它的回收是在系统判断内存不足的情况下进行的,因此相对于强引用来说,软引用更容易被回收。
在Java中,可以使用java.lang.ref.SoftReference类来创建软引用。例如:
import java.lang.ref.SoftReference;public class SoftReferenceExample {public static void main(String[] args) {// 创建一个字符串对象并使用软引用引用它String data = new String("Soft Reference Example");SoftReference<String> softReference = new SoftReference<>(data);// 现在,data可以被释放了,因为只有软引用引用它data = null;// 从软引用中获取对象String retrievedData = softReference.get();System.out.println(retrievedData);// 在这里模拟内存不足的情况simulateMemoryFull();// 再次尝试获取对象,如果内存不足,软引用可能被垃圾回收器回收retrievedData = softReference.get();System.out.println(retrievedData);}private static void simulateMemoryFull() {// 在这个方法中,模拟内存不足的情况,触发垃圾回收// 实际场景中,内存不足的情况可能由系统触发System.gc();} }
在这个例子中,字符串对象被创建后,通过软引用 softReference 引用。然后,将 data 设置为 null,这意味着只有软引用引用这个字符串对象。在模拟内存不足的情况时,垃圾回收器可能会回收这个字符串对象。
需要注意的是,软引用并不是一种确保对象被回收的机制,而是一种提供更灵活的回收策略的手段。软引用通常用于缓存等场景,允许在内存不足时释放一些缓存数据,而不会导致程序崩溃。
-
弱引用
弱引用(Weak Reference)是Java中一种比软引用更弱的引用类型。与软引用类似,弱引用在垃圾回收时对对象的保护程度更低。当一个对象只被弱引用引用时,它在下一次垃圾回收时就有可能被回收,无论当前内存是否足够。
在Java中,可以使用 java.lang.ref.WeakReference 类来创建弱引用。以下是一个简单的示例:
import java.lang.ref.WeakReference;public class WeakReferenceExample {public static void main(String[] args) {// 创建一个字符串对象并使用弱引用引用它String data = new String("Weak Reference Example");WeakReference<String> weakReference = new WeakReference<>(data);// 现在,data可以被释放了,因为只有弱引用引用它data = null;// 从弱引用中获取对象String retrievedData = weakReference.get();System.out.println(retrievedData);// 在这里模拟内存不足的情况simulateMemoryFull();// 再次尝试获取对象,由于只有弱引用引用,对象可能被垃圾回收retrievedData = weakReference.get();System.out.println(retrievedData);}private static void simulateMemoryFull() {// 在这个方法中,模拟内存不足的情况,触发垃圾回收// 实际场景中,内存不足的情况可能由系统触发System.gc();} }
在这个例子中,字符串对象被创建后,通过弱引用 weakReference 引用。然后,将 data 设置为 null,这意味着只有弱引用引用这个字符串对象。在模拟内存不足的情况时,垃圾回收器可能会回收这个字符串对象。
弱引用通常用于一些临时性的缓存,当被引用对象不再被其他强引用引用时,垃圾回收器可以更自由地回收它们。弱引用的典型应用场景包括实现一些缓存策略,其中缓存项可以在内存紧张时被更容易地回收。
-
虚引用
虚引用(Phantom Reference)是Java中最弱的一种引用类型,与弱引用和软引用不同,虚引用的存在几乎没有直接的影响。虚引用主要用于跟踪对象被垃圾回收的状态。
在Java中,可以使用 java.lang.ref.PhantomReference 类来创建虚引用。虚引用并不能通过 get() 方法获取被引用的对象,而是通过配合引用队列(ReferenceQueue)来使用。当虚引用引用的对象被垃圾回收时,虚引用会被加入到引用队列中。
以下是一个简单的虚引用示例:
import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue;public class PhantomReferenceExample {public static void main(String[] args) {// 创建一个字符串对象并使用虚引用引用它String data = new String("Phantom Reference Example");ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();PhantomReference<String> phantomReference = new PhantomReference<>(data, referenceQueue);// 现在,data可以被释放了,因为只有虚引用引用它data = null;// 在这里检查引用队列,看是否有虚引用进入// 虚引用入队后,表示对象即将被回收ReferenceQueue<String> queue = new ReferenceQueue<>();PhantomReference<String> phantomRef = new PhantomReference<>(data, queue);// 模拟垃圾回收的动作System.gc();// 检查引用队列,看是否有虚引用进入// 虚引用入队后,表示对象即将被回收java.lang.ref.Reference<? extends String> polledReference = referenceQueue.poll();if (polledReference != null) {System.out.println("PhantomReference is enqueued.");} else {System.out.println("PhantomReference is not enqueued.");}} }
在这个例子中,字符串对象被创建后,通过虚引用 phantomReference 引用。然后,将 data 设置为 null,这意味着只有虚引用引用这个字符串对象。在模拟垃圾回收的动作时,我们检查引用队列,如果虚引用已经进入队列,表示相关对象即将被回收。
虚引用通常用于一些特殊的清理操作,例如在对象被回收时执行一些资源释放或日志记录等。由于虚引用的特性,它并不能阻止被引用对象的回收。
-
终结器引用
在Java中,终结器引用(Finalizer Reference)是一种与对象终结器(Finalizer)相关的引用。对象终结器是一个用于在对象被垃圾回收前执行清理操作的特殊方法,它由Object类中的finalize方法表示。
终结器引用通常与对象的终结器方法相关联,通过 java.lang.ref.Finalizer 类进行管理。然而,需要注意的是,终结器机制在现代Java中被认为是不推荐使用的,因为它的执行时机不确定性,可能导致一系列问题,如内存泄漏和性能问题。
以下是一个简单的示例,演示了终结器引用的使用:
import java.lang.ref.Finalizer;class MyObject {@Overrideprotected void finalize() throws Throwable {System.out.println("Finalizing MyObject");} }public class FinalizerReferenceExample {public static void main(String[] args) {MyObject obj = new MyObject();// 创建终结器引用Finalizer<MyObject> finalizerReference = new Finalizer<>(obj, null);// 将对象置为null,使对象变为可终结obj = null;// 请求垃圾回收System.gc();// 在垃圾回收后,finalize方法可能被调用// 但不推荐依赖finalize方法执行清理操作} }
在这个例子中,MyObject类重写了finalize方法,然后通过 Finalizer 类创建了一个终结器引用。当垃圾回收器请求垃圾回收时,finalize方法可能被调用。
然而,强烈建议不要过度依赖终结器机制。替代终结器的方法包括使用try-with-resources结构、AutoCloseable接口以及其他清理模式。这些方法能够提供更可靠、可预测和有效的资源管理。
2. 垃圾回收算法
2.1 标记清除
标记清除算法(Mark and Sweep Algorithm)是一种基本的垃圾回收算法,用于找出不再被程序引用的对象并释放它们所占用的内存。该算法主要分为两个阶段:标记阶段和清除阶段。
以下是标记清除算法的基本步骤:
- 标记阶段(Marking Phase):
从根对象(GC Roots)开始,通过遍历对象引用链,标记所有被引用的对象。这个过程确保所有可达的对象都被标记为活动对象。
- 清除阶段(Sweeping Phase):
在清除阶段,垃圾回收器遍历整个堆,清除未被标记的对象。即,垃圾回收器释放那些没有在标记阶段被标记为活动对象的内存。清除的对象会被加入到可用的内存池,等待下次分配。
标记清除算法的优点在于它能够处理循环引用,因为它通过标记活动对象的方式,确保只有活动对象能够被保留。然而,这种算法也有一些缺点,例如:
-
碎片化问题: 由于清除阶段释放的内存是不连续的,可能导致堆中出现碎片化,从而降低了内存的使用效率。
-
效率问题: 清除阶段需要遍历整个堆,这在堆较大时可能会导致较长的停顿时间。
由于这些缺点,现代垃圾回收算法往往采用其他更高效的算法,如复制算法、标记-整理算法等。标记清除算法在教育和理论研究中仍然具有重要的地位,但在实际应用中,往往会选择更先进的垃圾回收算法。
2.2 标记整理
标记整理算法(Mark and Compact Algorithm)是一种垃圾回收算法,它结合了标记阶段、整理阶段和清除阶段,旨在减少内存碎片化。这个算法主要用于堆的管理,确保存活的对象在内存中是紧凑排列的,而非出现碎片。
以下是标记整理算法的基本步骤:
- 标记阶段(Marking Phase):
从根对象开始,通过遍历对象引用链,标记所有被引用的对象,将它们标记为活动对象。
- 整理阶段(Compacting Phase):
在整理阶段,垃圾回收器将所有活动对象向一端(通常是堆的起始端)移动,以便在移动过程中将空闲空间集中到堆的另一端。这一步骤类似于复制算法,但标记整理算法并不创建一个新的空间,而是在原有的堆中进行整理。
- 清除阶段(Sweeping Phase):
在清除阶段,垃圾回收器遍历整个堆,清除未被标记的对象。即,垃圾回收器释放那些没有在标记阶段被标记为活动对象的内存。
标记整理算法的优势在于它避免了标记清除算法的碎片化问题。通过整理阶段,存活的对象被移动到一起,而空闲的内存空间则被集中在一起,使得内存分配更为高效。但与此同时,标记整理算法仍然可能存在一定的停顿时间,因为整理阶段可能需要移动大量对象。
虽然标记整理算法在解决内存碎片问题上表现良好,但在某些场景下,如实时性要求较高的应用中,仍然可能会选择其他垃圾回收算法,如分代垃圾回收算法。
2.3 复制算法
复制算法(Copying Algorithm)是一种垃圾回收算法,主要用于解决内存碎片化的问题。该算法将堆分为两个区域:一个是活动对象存放的From空间,另一个是空闲空间的To空间。在每次垃圾回收时,将所有存活的对象从From空间复制到To空间,同时将From空间清空,然后交换From和To的角色,使得下一次垃圾回收时复制存活对象到新的To空间。
以下是复制算法的基本步骤:
- 标记阶段(Marking Phase):
从根对象开始,通过遍历对象引用链,标记所有被引用的对象,将它们标记为活动对象。
- 复制阶段(Copying Phase):
将所有活动对象从From空间复制到To空间。由于复制过程中保持了对象的相对顺序,因此无需移动引用。
- 更新引用(Update References):
更新所有指向被复制的对象的引用,使其指向新的To空间中的地址。
- 角色交换(Swap Roles):
交换From和To的角色,使To空间成为下一次垃圾回收的From空间。
复制算法的优点在于它解决了内存碎片的问题,因为新的To空间是一块干净的连续内存。然而,这种算法的缺点是它浪费了一半的内存空间,因为每次垃圾回收都需要有一块足够大的To空间来容纳所有活动对象。
复制算法通常用于新生代的垃圾回收,而在分代垃圾回收中,新生代采用复制算法,老年代则采用其他算法,如标记清除或标记整理算法。这样可以更好地平衡内存利用和垃圾回收效率。
3. 分代垃圾回收
分代垃圾回收是一种垃圾回收策略,根据对象的存活周期将堆内存划分为不同的代(Generation),并采用不同的垃圾回收算法和频率来处理每个代。这种策略基于两个观察:
- 弱存活假说(Weak Generational Hypothesis):
大部分对象在内存中存在的时间很短,而只有一小部分对象存活得较长。因此,可以将对象划分为新生代和老年代,分别采用不同的垃圾回收算法。
- 新生代的对象更容易死亡(Most objects die young):
大多数对象在被分配后很快就变得不可达,因此新生代中的对象更容易死亡。
分代垃圾回收一般将堆划分为三代:
- 新生代(Young Generation):
这是对象刚被分配的地方。新生代中的对象大多数是短命的。典型的垃圾回收算法是复制算法,因为复制算法适用于高回收率的场景。
- 老年代(Old Generation):
这是新生代中存活时间较长的对象被晋升到的地方。老年代中的对象更有可能长时间存活,因此采用标记清除或标记整理算法。
- 永久代(Permanent Generation):
用于存放静态不变的类信息、方法信息等。在JDK 8及以后的版本中,永久代被元空间(Metaspace)取代。
分代垃圾回收的优势在于它针对不同代采用不同的垃圾回收策略,根据对象的生命周期进行优化。这可以降低整体垃圾回收的成本,提高垃圾回收的效率。在实践中,分代垃圾回收策略被广泛应用于Java虚拟机和其他语言的运行时系统中。
4. 垃圾回收器
垃圾回收器是一种用于自动管理程序运行时内存的机制,它负责检测和回收不再被程序使用的内存对象,以便释放资源并防止内存泄漏。在Java和其他高级编程语言中,垃圾回收器是运行时系统的一部分。
以下是一些常见的垃圾回收器:
- 串行垃圾回收器(Serial Garbage Collector):
串行垃圾回收器是最基本的垃圾回收器,它使用单线程进行垃圾回收操作。适用于小型或简单的应用程序,但在大型应用中可能导致停顿时间较长。
- 并行垃圾回收器(Parallel Garbage Collector):
并行垃圾回收器使用多个线程进行垃圾回收操作,提高了垃圾回收的效率。适用于多核处理器的系统,可减少垃圾回收造成的停顿时间。
- 并发标记清除垃圾回收器(Concurrent Mark-Sweep Garbage Collector,CMS):
CMS垃圾回收器使用多线程进行标记和清除操作,以减少停顿时间。它适用于对停顿时间敏感的应用程序,但可能会牺牲一些吞吐量。
- G1垃圾回收器(Garbage First Garbage Collector):
G1垃圾回收器是一种面向大堆内存的垃圾回收器,旨在提供低停顿时间和高吞吐量。它将堆划分为多个区域,通过优先处理垃圾量较小的区域来降低停顿时间。
- Z垃圾回收器(Z Garbage Collector):
Z垃圾回收器是JEP 333引入的一种低停顿时间的垃圾回收器。它使用了一种称为Colored Pointers的技术,通过并发标记和整理的方式,减少了垃圾回收引起的停顿时间。
- Shenandoah垃圾回收器:
Shenandoah是一种低停顿时间的垃圾回收器,旨在减小大堆内存的垃圾回收停顿时间。它使用了一种被称为"Concurrent Compacting"的技术,通过并发标记和压缩来实现低停顿时间。
这些垃圾回收器具有不同的特性,选择哪个垃圾回收器取决于应用程序的性能需求、硬件配置以及对停顿时间的敏感性。在某些情况下,可以通过Java虚拟机的参数来选择或配置垃圾回收器。
5. 垃圾回收调优
JVM(Java Virtual Machine)的垃圾回收调优是优化Java应用程序性能和减少垃圾回收停顿时间的关键部分。以下是一些常见的JVM垃圾回收调优技巧:
-
选择合适的垃圾回收器:
根据应用程序的性能需求和硬件配置,选择适合的垃圾回收器。例如,对于对停顿时间敏感的应用程序,可以考虑使用CMS(Concurrent Mark-Sweep)或G1(Garbage First)垃圾回收器。如果系统具有多核处理器,可以考虑使用并行垃圾回收器。
-
调整堆大小:
根据应用程序的内存使用情况,调整堆的大小。合理的堆大小可以降低垃圾回收的频率,减小停顿时间。可以使用-Xms和-Xmx参数分别设置堆的初始大小和最大大小。
java -Xms256m -Xmx512m -jar YourApplication.jar
-
选择合适的垃圾回收策略:
根据应用程序的内存使用模式,选择合适的垃圾回收策略。例如,对于短时间存活的对象较多的应用,考虑使用串行垃圾回收器或Parallel垃圾回收器。对于大堆内存,可以尝试使用G1垃圾回收器。
-
设置垃圾回收器相关的参数:
针对选择的垃圾回收器,可以调整相关的参数。例如,对于CMS垃圾回收器,可以使用-XX:MaxGCPauseMillis参数设置最大停顿时间。
java -XX:+UseConcMarkSweepGC -XX:MaxGCPauseMillis=500 -jar YourApplication.jar
-
监控和分析垃圾回收日志:
启用垃圾回收日志并进行监控分析是调优的重要手段。可以使用-XX:+PrintGCDetails和-Xloggc:gc.log参数来生成详细的垃圾回收日志。
java -XX:+PrintGCDetails -Xloggc:gc.log -jar YourApplication.jar
使用工具如jvisualvm、jConsole或专业的监控工具,对垃圾回收的情况进行实时监控和分析,以便及时发现潜在问题。
-
避免过度内存分配:
减少不必要的对象创建和过度的内存分配有助于降低垃圾回收的压力。避免创建大量临时对象,尽可能使用对象池或重用对象的方式。
-
分析应用程序的内存使用情况:
使用内存分析工具,如Eclipse Memory Analyzer(MAT)或VisualVM,深入了解应用程序的内存使用情况,找出可能的内存泄漏或不必要的内存占用。
这些调优技巧需要结合具体应用程序的特点进行调整,因为不同的应用有不同的内存使用模式和性能需求。定期进行性能测试和监控是调优的关键。
相关文章:
JVM之垃圾回收
1. 如何判断对象可以回收 1.1 引用计数法 引用计数法是一种内存管理技术,其中每个对象都有一个与之关联的引用计数。引用计数表示当前有多少个指针引用了该对象。当引用计数变为零时,表示没有指针再指向该对象,该对象可以被释放,…...

人工智能基础_机器学习026_L1正则化_套索回归权重衰减梯度下降公式_原理解读---人工智能工作笔记0066
然后我们继续来看套索回归,也就是线性回归,加上了一个L1正则化对吧,然后我们看这里 L1正则化的公式是第二个,然后第一个是原来的线性回归,然后 最后一行紫色的,是J= J0+L1 对吧,其实就是上面两个公式加起来 然后我们再去看绿色的 第一行,其实就是原来线性回归的梯度下降公式…...
ubuntu xrdp远程登录一直弹出Authentication required. System policy prevents WiFi scans
windows远程登录以后想要连接一下wifi,一定弹出Authentication required,关都关不掉,wifi也连不上。 使用以下方法后完美解决 sudo vi /etc/polkit-1/localauthority/50-local-d/network.pkla 加入如下内容: [Allow Wifi Scan…...

【Python】基础练习题_ 函数和代码复用
(1)编写一个函数,输入n为偶数时,调用函数求1/21/4…1/n,当输入n为奇数时,调用函数1/11/3…1/n。 def calculate_sum(n):total_sum 0if n % 2 0: # n为偶数for i in range(2, n1, 2):total_sum 1 / ielse: # n为奇…...
Java中的ClassLoader是什么?有哪些常见的ClassLoader?
在Java中,ClassLoader是一个抽象类,它的主要任务就是将class文件加载到JVM虚拟机中去以便程序可以正确运行。一般来说,Java程序在编写完成后是以.java的文件存在磁盘上,然后通过编译器将其编译成.class文件(字节码文件…...

vim批量多行缩进调整
网上其他教程: ctrl v 或者 v进行visual模式按方向键<,>调整光标位置选中缩进的行Shift > (或者 Shift < )进行左右缩进。 我只想说,乱七八糟,根本不管用 本文教程: 增加缩进…...

MATLAB|科研绘图|山脊图
效果图 山脊图介绍 山脊图(Ridge Plot),也被称为Joy Plot,是一种用于可视化数据分布的图表,特别是用于显示多个组的分布情况。在这种图表中,每个组的数据分布都通过平滑的密度曲线来表示,这些曲…...

Python编程爬虫代码
这是一个基本的爬虫程序的示例,按照你的需求进行了修改: typescript import * as request from request; import * as cheerio from cheerio; const proxyHost ; const proxyPort ; // 创建一个request实例,使用 const requestWithProxy…...

工作汇报怎么写?建议收藏
整体思路与模块: 背景/事件 成果展示 推动落实的方法论 收获与成长 存在的不足及改进措施 下一步工作安排 支持(选) 一、背景/事件 对于区分“功能性总结”和“应付性总结”,在背景/事件方面有一个关键点 是报告是否具有…...

动作捕捉系统通过VRPN与ROS系统通信
NOKOV度量动作捕捉系统支持通过VRPN与机器人操作系统ROS通信,进行动作捕捉数据的传输。 一、加载数据 打开形影动捕软件,加载一段后处理数据。 这里选择一段小车飞机的同步数据。在这段数据里面,场景下包含两个刚体,分别是小车和…...

Java Stream 的常用API
Java Stream 的常用API 遍历(forEach) package com.liudashuai;import java.util.ArrayList; import java.util.List;public class Test {public static void main(String[] args) {List<Person> userList new ArrayList<>();userList.ad…...

代驾预约小程序系统源码 :提起预约,避免排队 带完整搭建教程
大家好啊,又到罗峰来给大家分享好用的源码系统的时间了。今天要给大家分享的第一款代驾预约小程序源码系统。传统的代驾服务中,用户往往需要在酒后代驾、长途驾驶等场景下,面对排队等待代驾司机空闲时间的繁琐过程。这不仅浪费了用户的时间和…...
es 报错 Data too large 触发断路器
文章目录 [toc]事出有因解决思路效果展示关于重启课外扩展 事出有因 报错原因是 es 在 full GC 之前触发了默认的断路器,导致报错 [parent] Data too large,相似的报错内容如下: Caused by: org.elasticsearch.common.breaker.CircuitBreakin…...

idea报[Ubuntu] File watcher failed repeatedly and has been disabled
1.安装File Watchers 2.restart idea解决...

phpstudy 开启目录浏览功能
(1)在该目录下: (2)选择对应网站的配置文件; (3)修改: # Options FollowSymLinks ExecCGI Options Indexes FollowSymLinks ExecCGI...

【前端开发】图例宽度根据数值自适应
前端开发 先看结果图 图例的宽度会随数值的改变而变化。 HTML部分 <!-- 数值部分 --> <ul class"tuli" ref"num"><listyle"margin-top: 5px;padding: 0 5px;text-align: center;"v-for"item of itemArr":key"i…...

AOMedia发布免版税沉浸音频规范IAMF
11月10日,开放媒体联盟(AOMedia)发布了旗下首个沉浸式音频规范IAMF(https://aomediacodec.github.io/iamf/),IAMF是一种编解码器无关的容器规范,可以携带回放时间渲染算法和音频混音的信息&…...

Linux C 进程编程
进程编程 进程介绍进程的定义进程和线程以及程序的区别进程块PCB进程的状态相关指令 进程调度算法先来先服务调度算法 FCFS短作业(进程)优先调度算法 SJF优先权调度算法 FPF优先权调度算法的类型非抢占式优先权算法抢占式优先权算法 优先权类型静态优先权动态优先权 高响应比优…...

Spring Boot (三)
1、热部署 热部署可以替我们节省大把花在重启项目本身上的时间。热部署原理上,一个springboot项目在运行时实际上是分两个过程进行的,根据加载的东西不同,划分成base类加载器与restart类加载器。 base类加载器:用来加载jar包中的类…...
第五章:抽象类
系列文章目录 文章目录 系列文章目录前言一、抽象类二、模板设计模式总结 前言 当我们想让子类来实现方法时,我们需要抽象类与抽象方法。 一、抽象类 当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

ZYNQ学习记录FPGA(二)Verilog语言
一、Verilog简介 1.1 HDL(Hardware Description language) 在解释HDL之前,先来了解一下数字系统设计的流程:逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端,在这个过程中就需要用到HDL,正文…...
Docker、Wsl 打包迁移环境
电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本: 2.2.4.0 内核版本: 5.15.153.1-2 WSLg 版本: 1.0.61 MSRDC 版本: 1.2.5326 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.2609…...