JVM 中“對象存活判定方法”全面解析

1. 前言

在 Java 開發過程中,我們常常聽到“垃圾回收”(Garbage Collection, GC)這一術語。JVM 通過垃圾回收機制自動管理內存,極大地簡化了程序員的內存控制負擔。然而,GC 究竟是如何判斷哪些對象該回收、哪些應保留的呢?這正是“對象存活判定”的關鍵所在。

對象存活判定方法的效率和準確性,直接關系到系統性能的高低。在內存緊張的場景中,一個不合理的回收策略可能導致頻繁 GC,甚至導致 OutOfMemoryError(OOM)錯誤。

Java 語言自誕生之初就非常重視內存安全問題,JVM 也隨著版本更新不斷優化垃圾回收算法。目前主流的 Java 8 就采用了更加高效的“可達性分析法”替代傳統的“引用計數法”,以規避引用循環等典型問題。

本系列文章將從基礎原理入手,深入剖析 JVM 如何判斷對象是否“還活著”,并配合圖解與示例代碼,幫助開發者更好地理解這一 GC 背后的核心機制。

閱讀后你將收獲:

  • JVM 內存模型與對象管理原理

  • 引用計數法與可達性分析法的差異與優劣

  • 如何用代碼分析對象是否會被 GC 回收

  • 實用工具(MAT、JVisualVM)的分析技巧

讓我們從最基礎的問題開始——“對象存活判定”到底指的是什么?

2. 什么是對象存活判定?

對象存活判定(Object Liveness Detection)是指 JVM 在垃圾回收過程中判斷某個對象是否仍“有用”的一套邏輯機制。只有當 JVM 確認一個對象“無用”時,才會將其內存空間釋放。

那么,什么是“有用”或“無用”?這個標準并非由程序員顯式指定,而是 JVM 通過一定的算法推導得出。

從 JVM 的角度來看:

  • “有用”的對象:程序仍然可以訪問到該對象。

  • “無用”的對象:程序中不再有任何方式可以訪問到該對象。

這就涉及到兩個關鍵問題:

  1. 程序如何“訪問”一個對象?

  2. JVM 如何判斷“是否還能訪問”?

為了解決這兩個問題,JVM 提供了兩種主要的判斷方式:

  • 引用計數法(Reference Counting):為每個對象維護一個引用計數器。

  • 可達性分析法(Reachability Analysis):從一組被稱為 GC Roots 的起點出發,遍歷對象圖。

這兩種方法各有利弊,也體現了 JVM 垃圾回收策略的演進方向。

在接下來的章節中,我們將逐一剖析這兩種算法的底層原理、適用場景與實現機制,并結合示意圖和代碼說明其工作方式。

3. 方法一:引用計數法

基本原理

引用計數法的核心思想非常直觀:

每當有一個地方引用該對象,其引用計數就加 1; 每當有一個引用失效,其引用計數就減 1; 當引用計數為 0 時,說明該對象“無人引用”,可以回收。

這一機制類似于手動管理內存語言(如 C++ 的智能指針),但在 Java 中并未采用這種方式作為主流實現。

示意圖

假設我們有以下引用關系:

A --> B --> C^     ||_____|
  • 對象 A 引用了 B,B 引用了 C,C 又回頭引用了 B,構成循環引用。

  • 即便 A 被回收,B 與 C 相互引用,導致引用計數不為 0,從而無法釋放。

這就是引用計數法的致命缺陷:無法處理對象之間的循環引用問題

示例代碼

雖然 Java 官方并未公開支持引用計數 GC,但我們可以通過偽代碼演示其原理:

class MyObject {int refCount = 0;void addReference() {refCount++;}void removeReference() {refCount--;if (refCount == 0) {// 回收對象內存System.out.println("對象可以被回收");}}
}

使用時:

MyObject obj = new MyObject();
obj.addReference(); // 引用 +1
obj.removeReference(); // 引用 -1,若為0則可回收

當然,實際 JVM 中并未使用這種方法來管理對象生命周期。

優缺點分析

優勢劣勢
算法實現簡單,效率高無法處理循環引用
回收實時性好增加引用維護成本
易于實現跨語言互操作與現代 JVM 架構不兼容

因此,雖然引用計數法在一些腳本語言(如 Python)或 C++ 的智能指針中應用較多,但在 Java JVM 中并未成為主流方法。

下一節我們將介紹 JVM 真正使用的對象存活判定方式:可達性分析法(Reachability Analysis)

4. 方法二:可達性分析法

GC Roots 概念

可達性分析法(Reachability Analysis)是目前 Java 虛擬機中對象存活判定的主流算法。

該方法的核心思想是:通過從一組稱為 "GC Roots" 的起始節點出發,沿著對象引用鏈向下搜索,如果某個對象從 GC Roots 出發可達,則說明該對象是“活著”的;否則就會被判定為“死亡”。

GC Roots 的起始節點通常包括:

  • 虛擬機棧(棧幀中的本地變量表)中引用的對象

  • 方法區中類靜態屬性引用的對象

  • 方法區中常量引用的對象

  • 本地方法棧中 JNI 引用的對象

我們將在后續的章節中深入介紹這些 GC Roots 的類型。

分析流程

整個分析過程可以類比成遍歷一張“對象圖”:

  1. 建立對象引用圖(Object Graph) 所有對象通過引用連接形成有向圖,圖中的邊代表引用關系。

  2. 標記可達對象 從 GC Roots 出發,標記所有可到達的對象,形成“可達集合”。

  3. 未被標記的對象即為不可達對象 這些不可達的對象被視為垃圾,等待 GC 清理。

注意:即使對象不可達,JVM 并不會立刻回收它。 如果該對象覆蓋了 finalize() 方法,還會進入一次“F-Queue”隊列,被 GC 再次確認其是否真的不可用。

圖解說明

            [GC Roots]|-------------------------|           |           |Obj1        Obj2       Obj3|                       |Obj4                   Obj5Obj6 (無法從 GC Roots 到達)
  • Obj1~Obj5 均從 GC Roots 可達,為存活對象。

  • Obj6 無任何引用鏈連接至 GC Roots,被視為“死亡對象”。

示例代碼演示

雖然 JVM 自動完成對象圖的構建和遍歷,我們無法直接干預,但可以通過示例展示“對象是否可達”的效果:

public class ReachabilityDemo {static class Node {String name;Node reference;Node(String name) {this.name = name;}@Overrideprotected void finalize() throws Throwable {System.out.println(name + " 被回收了");}}public static void main(String[] args) {Node a = new Node("A");Node b = new Node("B");Node c = new Node("C");a.reference = b;b.reference = c;a = null; // 去除對 A 的強引用b = null; // 去除對 B 的強引用c = null; // 去除對 C 的強引用System.gc(); // 顯式請求 GCtry {Thread.sleep(1000); // 等待 GC 完成} catch (InterruptedException e) {e.printStackTrace();}}
}

輸出示例:

C 被回收了
B 被回收了
A 被回收了

說明 A、B、C 都在不可達狀態下被 GC 回收。

優勢與 JVM 的支持

優點說明
能解決循環引用問題不依賴引用計數值,識別結構關系
更適合復雜對象圖圖遍歷可適配大型堆場景
JVM 官方支持Java 8 及以后的所有主流 JVM 均基于該方法

下一節我們將具體介紹 GC Roots 中的各類節點來源,幫助大家更深入理解對象“可達”的起點到底是什么。

?

5. GC Roots 的類型

在上一節中我們提到,GC Roots 是可達性分析的起點。那么,GC Roots 到底是什么?哪些對象或引用屬于 GC Roots?理解 GC Roots 是掌握 JVM 垃圾回收機制的核心一步。

GC Roots 主要包括以下幾種類型的引用:

1. 虛擬機棧中的引用(局部變量表)

每個線程在執行方法時都會創建一個棧幀(Stack Frame),其中的局部變量表中保存著各種基本類型和對象引用。

public class StackReferenceDemo {public static void main(String[] args) {Object obj = new Object(); // obj 是 GC Root 引用System.gc();}
}

在這個例子中,obj 是定義在主方法中的局部變量,它保存在棧幀的局部變量表中,因此是 GC Roots。

2. 方法區中類靜態屬性引用的對象

靜態字段隨著類的加載而存在于方法區中,引用的對象也會被視為 GC Roots。

public class StaticReferenceDemo {private static Object staticObj = new Object(); // 屬于 GC Rootpublic static void main(String[] args) {System.gc();}
}

即使沒有局部變量引用 staticObj,它依然不會被 GC,因為它是類的靜態屬性。

3. 方法區中常量引用的對象

常量池中的引用,如字符串常量等,也是 GC Roots 的一部分。

public class ConstantPoolDemo {public static void main(String[] args) {String str = "hello world"; // 字符串常量常駐內存System.gc();}
}

在這個例子中,字符串 "hello world" 常駐在運行時常量池中,是 GC Roots 的一部分,不會被回收。

4. 本地方法棧中的 JNI 引用(Native 引用)

如果 Java 程序調用了本地方法(如 C/C++ 實現的庫),這些 native 方法中持有的對象引用也會被當作 GC Roots。

public class JNIDemo {static {System.loadLibrary("native-lib");}public native void callNative();
}

雖然無法用 Java 展示 native 層引用的具體內容,但這些引用 JVM 會在 GC 時特殊處理。

5. 活躍線程

所有運行中的線程(如主線程、GC線程、后臺線程等)都是 GC Roots,因為它們自身的引用鏈天然“存活”。只有當線程執行結束、退出后,它們才會從 GC Roots 移除。

6. JVM 內部保留的系統類加載器

例如 sun.misc.Launcher$AppClassLoaderExtClassLoader 等,這些類加載器加載的類及其引用的對象會被視為 GC Roots。

7. JDK 特殊結構

System.in/out/err、線程上下文類加載器、反射中的 Method/Field/Constructor 對象、線程組等。這些結構大多存在于系統級類中,使用時容易導致內存泄露。

總結 GC Roots 類型

GC Roots 類型是否常見是否手動可控
虛擬機棧引用? 常見? 可控
靜態屬性引用? 常見? 可控
常量池引用? 常見? 不建議操作
JNI 本地引用? 復雜? 不建議操作
活躍線程引用? 常見? 不可控
類加載器引用? 常見? 不可控
系統類結構引用? 隱蔽? 不可控

理解 GC Roots 的種類不僅有助于判斷哪些對象能被 GC 回收,也對分析內存泄露、優化引用管理非常有幫助。

在下一節中,我們將進一步探索 Java 中的 finalize() 機制,以及對象“搶救”自己的最后機會。

6. Finalize 機制與固定對象

即使一個對象在 GC Roots 的可達性分析中被判定為“不可達”,也不代表它立刻會被回收。Java 提供了一個“臨終遺言”機制,即 finalize() 方法,使對象有一次自我拯救的機會。

6.1 什么是 finalize()

finalize()java.lang.Object 類中的一個方法:

protected void finalize() throws Throwable {// 釋放資源或對象復活的鉤子方法
}

當對象第一次被判定為不可達時,GC 會檢查該對象是否覆蓋了 finalize() 方法,且該方法是否尚未被調用。如果滿足條件,JVM 會將該對象放入一個名為 Finalization Queue 的隊列中,由一個低優先級的 Finalizer 線程去執行其 finalize() 方法。

注意:每個對象的 finalize() 方法最多只會被調用一次。

6.2 finalize() 能做什么?

  • 釋放資源:用于釋放文件句柄、關閉網絡連接等非內存資源(但不推薦這么用,推薦使用 try-with-resources)。

  • 復活對象:對象在 finalize() 中如果再次賦值給 GC Roots 引用鏈中的某個變量,則對象會“復活”。

6.3 示例:對象的自我拯救

public class FinalizeRescueDemo {public static FinalizeRescueDemo OBJ = null;@Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println("finalize() 方法被調用");OBJ = this; // 對象復活!}public static void main(String[] args) throws InterruptedException {OBJ = new FinalizeRescueDemo();// 第一次 GC,對象有機會復活OBJ = null;System.gc();Thread.sleep(1000);System.out.println(OBJ != null ? "對象存活" : "對象死亡");// 第二次 GC,finalize() 不會再被調用OBJ = null;System.gc();Thread.sleep(1000);System.out.println(OBJ != null ? "對象存活" : "對象死亡");}
}

運行結果:

finalize() 方法被調用
對象存活
對象死亡

說明:第一次 GC 時 finalize() 被調用,OBJ 被重新引用,從而復活。第二次 GC 時不再執行 finalize(),對象被真正回收。

6.4 finalize() 的問題與風險

  • 不可控時機:執行時間不確定,依賴 GC。

  • 影響性能:JVM 要維護一個隊列和額外線程。

  • 風險隱患:對象復活邏輯可能導致資源泄露或更難以調試的 bug。

  • 已被廢棄:Java 9 開始標注為 @Deprecated,建議使用 java.lang.ref.Cleaner 替代。

6.5 替代方案:Cleaner

import java.lang.ref.Cleaner;public class CleanerDemo {private static final Cleaner cleaner = Cleaner.create();static class Resource implements Runnable {@Overridepublic void run() {System.out.println("資源被清理");}}public static void main(String[] args) {Object obj = new Object();cleaner.register(obj, new Resource());}
}

Cleaner 提供了比 finalize() 更輕量、可控的資源清理方式,推薦在現代 Java 項目中使用。

7. 不同引用類型與垃圾回收行為

Java Reference類及其實現類深度解析:原理、源碼與性能優化實踐

Java 中定義了四種不同級別的引用類型:強引用(Strong Reference)軟引用(Soft Reference)弱引用(Weak Reference)虛引用(Phantom Reference),它們在 JVM 中表現出不同的“生存權重”。理解這些引用類型對于資源緩存、內存優化和對象生命周期控制至關重要。

7.1 強引用(Strong Reference)

這是最常見的引用類型:

Object obj = new Object();

只要強引用還存在,GC 永遠不會回收該對象。

特性

  • 是默認引用類型。

  • 會阻止 GC 回收所指向的對象。

示例

public class StrongReferenceDemo {public static void main(String[] args) {Object obj = new Object();System.gc();System.out.println(obj != null ? "對象未被回收" : "對象被回收");}
}

輸出:對象未被回收

7.2 軟引用(Soft Reference)

軟引用是一種比較“溫柔”的引用。它在內存不足時才會被 GC 回收。

SoftReference<Object> softRef = new SoftReference<>(new Object());

常用于內存敏感的緩存。

示例

import java.lang.ref.SoftReference;public class SoftReferenceDemo {public static void main(String[] args) {Object obj = new Object();SoftReference<Object> softRef = new SoftReference<>(obj);obj = null;System.gc();if (softRef.get() != null) {System.out.println("軟引用對象仍存活");} else {System.out.println("軟引用對象被回收");}}
}

注意:此示例中的回收依賴內存狀況,可能不會立即觸發。

7.3 弱引用(Weak Reference)

弱引用在 GC 時總是會被回收。

WeakReference<Object> weakRef = new WeakReference<>(new Object());

特性

  • 非常適合使用在 ThreadLocal、元數據緩存等短生命周期場景。

示例

import java.lang.ref.WeakReference;public class WeakReferenceDemo {public static void main(String[] args) {Object obj = new Object();WeakReference<Object> weakRef = new WeakReference<>(obj);obj = null;System.gc();if (weakRef.get() != null) {System.out.println("弱引用對象仍存活");} else {System.out.println("弱引用對象被回收");}}
}

輸出:弱引用對象被回收

7.4 虛引用(Phantom Reference)

虛引用無法通過 get() 方法訪問,被用于對象被回收時收到通知。

PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), referenceQueue);

特點

  • 永遠不會阻止 GC。

  • 常與 ReferenceQueue 配合使用。

示例

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;public class PhantomReferenceDemo {public static void main(String[] args) {Object obj = new Object();ReferenceQueue<Object> queue = new ReferenceQueue<>();PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue);obj = null;System.gc();System.out.println("phantomRef.get(): " + phantomRef.get());System.out.println("是否進入 ReferenceQueue: " + (queue.poll() != null));}
}

輸出:

phantomRef.get(): null
是否進入 ReferenceQueue: true

說明:虛引用不會返回實際對象,只用于跟蹤對象是否已被 GC。

7.5 引用強度對比總結

引用類型是否影響 GC 回收典型用途是否可通過 get() 訪問對象
強引用普通對象引用
軟引用視內存情況而定內存敏感緩存
弱引用ThreadLocal、臨時元數據
虛引用是(立即回收)清理前回調通知

?

8. 垃圾收集器與對象存活判定策略

Java 虛擬機中的垃圾收集器(GC)負責自動管理堆內存,及時回收不再使用的對象。不同的垃圾收集器采用不同的算法和策略來判斷對象是否存活,從而決定是否回收。理解這些策略有助于優化程序性能和內存管理。

8.1 常見垃圾收集器簡介

收集器名稱特點適用場景
Serial GC(串行收集器)單線程執行,簡單高效適合小內存或單核環境
Parallel GC(并行收集器)多線程并行,吞吐量優先多核服務器環境
CMS GC(并發標記清理)低停頓,標記與清理并發執行對響應時間敏感的應用
G1 GC(Garbage First)分區管理,低停頓,適合大堆大內存多核服務器

?

8.2 對象存活判定的核心機制

無論使用哪種收集器,對象的存活判定都基于“可達性分析”(Reachability Analysis):

  • 從 GC Roots(如線程棧、靜態變量)開始,遍歷所有引用鏈。

  • 能被引用鏈訪問到的對象被認為是存活的,不回收。

  • 無法訪問的對象則被標記為可回收。

8.3 不同收集器的對象判定流程

Serial 和 Parallel 收集器

  • 標記-清除(Mark-Sweep)或標記-復制(Mark-Copy)算法

  • 先暫停應用(Stop-The-World),從 GC Roots 開始標記存活對象。

  • 清除未標記對象或復制存活對象到新空間。

CMS 收集器

  • 采用多階段并發標記:

    • 初始標記:暫停應用,標記直接可達對象。

    • 并發標記:應用線程運行時,標記間接可達對象。

    • 重新標記:短暫停止應用,完成標記遺漏部分。

    • 并發清理:清理不可達對象。

G1 收集器

  • 將堆劃分成多個固定大小的區域(Region)。

  • 并發標記階段識別每個區域的存活對象數量。

  • 優先回收存活對象少的 Region,減少停頓時間。

  • 支持混合回收:回收年輕代和部分老年代。

8.4 代碼示例:指定收集器啟動參數

# 使用 Serial GC
java -XX:+UseSerialGC -Xmx512m -Xms512m MyApp# 使用 CMS GC
java -XX:+UseConcMarkSweepGC -Xmx2g -Xms2g MyApp# 使用 G1 GC
java -XX:+UseG1GC -Xmx4g -Xms4g MyApp

使用 VisualVM 或 JVisualVM 可以觀察不同收集器下堆內存對象的存活情況。

9. 總結與實踐建議

本文全面解析了 JVM 中對象存活判定的核心機制及其應用,包括可達性分析、引用類型、Finalize機制、垃圾收集器對判定策略的影響等關鍵內容。

9.1 對象存活判定的核心是“可達性分析”

  • 通過從 GC Roots 出發遍歷引用鏈,判斷對象是否仍被程序訪問。

  • 只有不可達對象才有回收資格,確保安全且高效的內存管理。

9.2 多種引用類型助力內存優化

  • 強引用、軟引用、弱引用、虛引用各具特點,開發者可根據需求選擇不同引用,靈活控制對象生命周期和內存回收時機。

  • 理解它們的差異,有助于避免內存泄漏和提升程序穩定性。

9.3 Finalize機制存在風險,應盡量避免

  • finalize() 方法雖可讓對象“復活”,但執行時機不確定,且影響性能。

  • 推薦使用 java.lang.ref.Cleaner 替代,更加安全且高效。

9.4 不同垃圾收集器對對象存活判定實現有差異

  • 串行、并行、CMS 和 G1 GC 等采用各自的標記算法和階段,平衡吞吐量與延遲。

  • 了解垃圾收集器特性,合理配置 GC 參數,對提升系統性能至關重要。

9.5 實踐建議

  • 在開發中,優先確保對象引用鏈清晰,避免意外的強引用導致內存泄漏。

  • 結合軟弱引用,設計緩存等場景,提高內存利用率。

  • 監控和調優垃圾收集器,配合性能分析工具,及時發現和解決內存相關問題。

  • 避免依賴 finalize(),轉用 Cleaner 和顯式資源管理。

  • 對于大型應用,考慮采用 G1 或者更先進的收集器,兼顧響應和吞吐。

通過深入理解對象存活判定方法,開發者能更精準地控制內存管理,寫出高效、穩定的 Java 應用。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88528.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88528.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88528.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

蘋果公司高ROE分析

公司通過增加負債提升凈資產收益率&#xff08;ROE&#xff09;的核心機制在于財務杠桿效應和資本結構優化&#xff0c;以下從原理、操作路徑、風險邊界及蘋果案例四維度展開分析&#xff1a;名稱解釋&#xff1a; ROIC(投入資本回報率)&#xff1a;ROICNOPATInvested Capital …

【Linux系統】進程概念

1. 進程概念1.1 進程的本質核心定義用戶視角&#xff1a;程序的動態執行實例&#xff08;如同時運行多個Chrome窗口即多個進程&#xff09;。內核視角&#xff1a;資源分配的最小實體單位&#xff0c;獨享CPU時間片、內存空間和文件資源。現代定義&#xff1a;進程 內核數據結…

從LLM到VLM:視覺語言模型的核心技術與Python實現

本教程的完整代碼可以在GitHub上找到&#xff0c;如果你有任何問題或建議&#xff0c;歡迎交流討論。 引言&#xff1a;為什么需要VLM&#xff1f; 當我們與ChatGPT對話時&#xff0c;它能夠理解復雜的文字描述&#xff0c;生成流暢的回答。但如果我們給它一張圖片&#xff0c…

老系統改造增加初始化,自動化數據源配置(tomcat+jsp+springmvc)

老系統改造增加初始化&#xff0c;自動化數據源配置一、前言二、改造描述1、環境說明2、實現步驟簡要思考三、開始改造1、準備sql初始化文件2、啟動時自動讀取jdbc文件&#xff0c;創建數據源&#xff0c;如未配置&#xff0c;需要一個默認的臨時數據源2.1去掉sping mvc原本配置…

衛星通信終端天線的5種對星模式之二:DVB跟蹤

要實現穩定可靠的衛星通信&#xff0c;地面終端天線必須精準地對準遠方的衛星。對星的過程是一個不斷搜索、不斷逼近的過程&#xff0c;其目標是讓天線波束中心精確指向衛星&#xff0c;從而獲得最大信號接收與發射效率。 衛星通信終端天線的對星技術是保障衛星通信鏈路穩定的…

重構下一代智能電池“神經中樞”:GCKontrol定義高性能BMS系統級設計標桿

概述BMS&#xff08;電池管理系統&#xff09;作為新能源汽車動力電池與整車的核心紐帶&#xff0c;通過實時監控電壓、電流、溫度及SOC等參數&#xff0c;控制電池充放電過程&#xff0c;保障電池安全性與使用壽命。隨著電動汽車智能化發展&#xff0c;對BMS的響應速度、精度和…

面試150 對稱二叉樹

思路 聯想遞歸三部曲&#xff1a;傳入參數、遍歷方式、返回什么。本題聯想到先序遍歷的方式,需要遍歷整顆二叉樹,最后返回的是一個布爾值。然后我們需要傳入的是左子樹和左子樹的節點,然后分別進行比較。 # Definition for a binary tree node. # class TreeNode: # def __…

多線程的區別和聯系

進程和線程的區別和聯系1.一個進程可以包含多個線程&#xff0c;不能夠沒有線程2.進程是系統資源分配的基本單位&#xff0c;線程是系統調度執行的基本單位3.同一個進程里的線程之間&#xff0c;共用同一份系統資源4.線程是當下實現并發編程的主流方式&#xff0c;通過多線程&a…

兩個文件夾自動同步

兩個文件夾自動同步&#xff0c;非常簡單&#xff0c;利用一些工具就可以輕松做到&#xff0c;設置完源和目標文件夾&#xff0c;點擊啟動就馬上可以兩個文件夾自動同步&#xff0c;對于一些有文件同步、文件災備需求的老登&#xff0c;用起來會非常順手&#xff0c;比如PanguF…

虛擬商品交易維權指南:數字經濟時代的消費者權益保護

首席數據官高鵬律師數字經濟團隊創作AI輔助在元宇宙、NFT、虛擬情緒產品等新興領域蓬勃發展的今天&#xff0c;虛擬商品交易已成為數字經濟的重要組成部分。從游戲皮膚、在線課程到數字藏品&#xff0c;消費者在享受虛擬商品便捷性的同時&#xff0c;也面臨著諸多法律風險。作為…

mysql 一條語句的執行流程

文章目錄一條查詢語句的執行流程連接器管理連接權限校驗分析器優化器采樣統計優化器選錯索引改正執行器查詢緩存存儲引擎一條update語句的執行流程redo logredo log buffer結構redo log日志類型寫入時機配置innodb_flush_log_at_trx_commitbinlogredo log和binlog 對比配置兩階…

【視頻觀看系統】- 需求分析

&#x1f3af; 一、項目目標 構建一個功能完備的視頻觀看網站&#xff0c;用戶可以上傳、瀏覽、觀看視頻&#xff0c;并在觀看過程中實時發送/接收彈幕。系統具備良好的性能、可擴展性與用戶體驗&#xff0c;未來可逐步擴展為多媒體平臺。&#x1f464; 二、用戶角色分析用戶類…

模型驅動的架構MDA的案例

在一個企業資源規劃&#xff08;ERP&#xff09;系統開發項目中&#xff0c;目標是為一家中型制造企業打造一套高效且可擴展的管理系統&#xff0c;涵蓋訂單處理、庫存管理等多個業務模塊。項目團隊采用了 MDA 的設計思想進行開發。?首先是業務需求分析與計算獨立模型&#xf…

第一次搭建數據庫

本文詳細介紹第一次搭建數據庫安裝和配置過程, 包括卸載舊版本、下載安裝、配置服務、環境變量等等 第一步下載mysql 在下載之前需要檢查電腦上有沒有安裝mysql, 如果有再安裝, 80%就會有問題 檢查方法: 電腦-右鍵找到管理-服務-在服務中找有沒有mysql服務若有請先 1.停止服務 …

洛谷題解 | UVA1485 Permutation Counting

目錄題目描述題目思路AC 代碼題目描述 https://onlinejudge.org/external/14/p1485.pdf 題目思路 dp。 定義 dpi,jdp_{i,j}dpi,j? 為前 iii 個數的排列中恰好有 jjj 個小于號的排列總數。 考慮將數字 iii 插入到前 i?1i-1i?1 個數的排列中不同的位置&#xff1a; 如果…

飛算科技:以原創技術賦能電商企業數字化轉型

在電商行業從流量競爭邁向精細化運營的當下&#xff0c;技術能力已成為決定企業生存與發展的核心要素。然而&#xff0c;高并發場景下的系統穩定性、個性化推薦算法的迭代效率、營銷活動的快速響應等挑戰&#xff0c;讓許多電商企業陷入“技術投入大、見效慢”的困境。作為國家…

人工智能自動化編程:傳統軟件開發vs AI驅動開發對比分析

人工智能自動化編程&#xff1a;傳統軟件開發vs AI驅動開發對比分析 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 總有一行代碼&#xff0c;能點亮萬千星辰。 &#x1f50d; 在技術的宇宙中&#xff0c;我愿做永不停歇的探索者。 ? 用代碼丈量…

用java實現一個自定義基于logback的日志工具類

? 動態創建: 無需配置文件&#xff0c;通過代碼動態創建logback日志對象 ? Class對象支持: 使用LogUtil.getLogger(MyClass.class)的方式獲取日志 ? 日期格式文件: 自動生成info.%d{yyyy-MM-dd}.log格式的日志文件 ? 文件數量管理: 只保留最近3個文件&#xff0c;自動刪除歷…

面試現場:奇哥扮豬吃老虎,RocketMQ高級原理吊打面試官

“你了解RocketMQ的高級原理和源碼嗎&#xff1f;” 面試官推了推眼鏡&#xff0c;嘴角帶笑&#xff0c;眼神里透著一絲輕蔑。 奇哥笑而不語&#xff0c;開始表演。面試場景描寫 公司位于高樓林立的CBD&#xff0c;電梯直達28樓。面試室寬敞明亮&#xff0c;空氣中混著咖啡香與…

Django Nginx+uWSGI 安裝配置指南

Django Nginx+uWSGI 安裝配置指南 引言 Django 是一個高級的 Python Web 框架,用于快速開發和部署 Web 應用程序。Nginx 是一個高性能的 HTTP 和反向代理服務器,而 uWSGI 是一個 WSGI 服務器,用于處理 Python Web 應用。本文將詳細介紹如何在您的服務器上安裝和配置 Djang…