java基礎(六)jvm

1. JVM內存的五大核心區域 + 一個幫手

想象JVM運行程序時,需要劃分不同區域干不同的事。主要分為這五大塊,外加一個特殊幫手:

1.1 程序計數器 (Program Counter Register) - 你的“任務進度條”

  • 干啥的: 專門記錄當前線程執行代碼執行到哪一行了!就像你看書時用書簽記住看到哪一頁。

  • 特點:

    • 每個線程獨一份,互不干擾(線程私有)。

    • 是唯一絕對不會發生內存溢出(OutOfMemoryError)的區域。

    • 執行Java方法時,記錄下一條指令地址;執行本地方法(如C/C++寫的)時,值為空(undefined)。

  • 為啥必須私有? 想象多個工人(線程)共用一臺機器(CPU),CPU輪流給每人干活。工人A干到一半被叫停時,計數器幫A記住干到哪步了;等輪回來,A才能接著干。每個人的進度都不同,當然需要自己的“小本本”!

1.2 虛擬機棧 (Java Virtual Machine Stacks) - 你的“方法工作間”

  • 干啥的: 每個線程執行方法時,都需要一個臨時空間,存放這個方法自己的東西:局部變量、方法參數、計算的中間結果、方法結束后該回哪去。

  • 怎么工作: 每調用一個方法,就在棧里壓入一個“工作臺”(叫棧幀)。方法執行完,就把這個工作臺彈出銷毀。

  • 特點:

    • 每個線程獨有一個棧。

    • 局部變量存在這里(基本類型如int num=10;10,或者對象的引用地址)。

    • 可能出問題:

      • StackOverflowError:方法調用太深(比如無限遞歸自己),工作間堆滿了。

      • OutOfMemoryError如果JVM允許動態擴展棧但內存不足,或者創建線程時申請棧內存失敗,就會發生(相對少見,但可能)。

1.3 本地方法棧 (Native Method Stacks) - “外來幫手”的工作間

  • 干啥的: 和虛擬機棧類似,但是給JVM調用的本地方法(Native方法,比如用C/C++寫的)用的。

  • 特點: 在常用的HotSpot虛擬機里,它和虛擬機棧是合在一起的。同樣可能發生StackOverflowErrorOutOfMemoryError

1.4 Java堆 (Java Heap) - 超級“對象大倉庫”

  • 干啥的: 存放所有你new出來的對象實例和數組! 這是JVM內存中最大最重要的一塊區域。

  • 特點:

    • 所有線程共享! 大家都從這里取對象。

    • 程序一啟動就創建。

    • 垃圾回收(GC)的主戰場

    • 空間不夠且無法擴展時,會OutOfMemoryError: Java heap space

  • 內部結構 (重點!): 為了更好地管理對象和垃圾回收,堆又細分成幾塊:

    • 新生代 (Young Generation): 存放剛出生、活不久的對象。分三小格:

      • Eden區 (伊甸園): 新對象出生地!new出來的對象絕大部分先放這里。空間較小

      • Survivor區 (幸存者區): 兩個大小相等的區域(通常叫FromTo,或者S0S1)。經歷一次垃圾回收(Minor GC)還活著的對象,會從Eden移到其中一個Survivor區。兩個區來回倒騰,活過幾次GC的“老油條”才能晉升。

    • 老年代 (Old Generation / Tenured Generation): 存放活得久的對象。從新生代熬過幾次GC(默認15次)晉升上來的對象,或者特別大的對象(避免在新生代頻繁挪動),都住這里。空間較大

    • 大對象去哪? 比如一個超級大的數組(需要連續大塊內存)。它們通常直接進老年代!為啥?

      • 新生代空間小,放大對象容易塞滿,頻繁觸發GC,性能差。

      • 大對象在新生代頻繁挪動容易產生碎片(小空隙),后面可能沒地方放新的大對象。

      • 老年代空間大,放大對象更合適。(注意:具體策略可能因JVM實現和參數略有不同)

    • TLAB (Thread-Local Allocation Buffer): 堆是共享的,但頻繁new對象時搶堆鎖影響效率。JVM給每個線程在Eden區劃一小塊私有空間(TLAB),線程優先在這里分配對象,提升效率,分配滿了才去鎖堆申請新TLAB。

1.5 方法區 (Method Area) - “圖書館”+“檔案室” (JDK8+ 叫 元空間 Metaspace)

  • 干啥的: 存儲已被JVM加載的類信息(類名、父類、方法簽名、字段描述)、運行時常量池靜態變量(static)即時編譯器(JIT)編譯好的機器碼

  • 特點:

    • 邏輯上是堆的一部分,但有個別名“非堆”(Non-Heap)。

    • JDK8后重大變化:永久代(PermGen)被移除,改為元空間(Metaspace),使用操作系統的本地內存(不再占用堆空間),解決了老版本永久代容易內存溢出的問題。

    • 內存不足時也會OutOfMemoryError: Metaspace

  • 運行時常量池 (Runtime Constant Pool): 是方法區的一部分。存放類文件里寫好的常量(如字符串字面量"abc"、數字100、符號引用),并且運行時也能往里面加新常量(比如String.intern()方法)。

1.6 直接內存 (Direct Memory) - “外部倉庫”

  • 干啥的: 不屬于JVM規范定義的內存區域! 通過NIO庫(ByteBuffer.allocateDirect())申請使用的操作系統本地內存

  • 優點: 讓數據少在Java堆和操作系統內存之間來回拷貝(零拷貝),顯著提升IO性能(文件讀寫、網絡通信快很多)。

  • 缺點: 雖然快,但總量受你電腦總內存限制,申請太多或忘記釋放(依賴Cleaner機制和PhantomReference通知)也會導致OutOfMemoryError: Direct buffer memory

2. 堆(Heap) vs 棧(Stack) 大不同!

特點堆 (Heap)棧 (Stack)
用途存對象實例 (new出來的東西) 和數組存局部變量、方法參數、操作數棧、返回地址等
生命周期對象由GC決定何時回收 (不確定)方法結束,棧幀銷毀,局部變量立即消失 (確定)
速度相對較慢 (分配、回收、GC有開銷)非常快 (操作簡單,內存分配只是移動指針)
空間很大,可動態擴展 (-Xmx)較小,固定大小 (-Xss)
線程所有線程共享每個線程私有
存啥?對象本身基本類型的值對象的引用地址(指針)

關鍵點:棧里存對象本身嗎? 不是!棧里存的是基本類型值(如int a = 10;里的10)和對象的引用地址(理解成指向堆里那個真實對象的門牌號)。比如 MyObject obj = new MyObject();

  • new MyObject()里創建了一個真實對象。

  • obj 這個變量存在的當前方法棧幀里,它的值就是堆里那個對象的門牌號(引用地址)

3. 方法區里有什么寶貝?

  • 類元數據(類名、父類、方法簽名、字段描述、常量池等)

  • 運行時常量池(各種字面常量、符號引用 -> 解析后的直接引用)

  • 靜態變量(static修飾的變量)

  • 即時編譯器(JIT)編譯好的本地機器碼(優化后執行更快)

  • (在永久代時代) 類的方法字節碼 (JDK8+的元空間通常不存字節碼本身)

4. String字符串住哪里?有啥講究?

  • String對象本身也是對象,所以實例里。

  • JVM搞了個字符串常量池(String Pool)來優化字符串:

    • 在哪? JDK7及之后移到堆里(之前放在方法區的永久代)。

    • 作用: 對于字面量方式創建字符串(String s1 = "abc";),JVM會先去常量池找有沒有"abc"

      • 如果有,直接把池里的引用給你(不創建新堆對象)。

      • 如果沒有,就在堆里的字符串常量池區域創建一個"abc"對象,再把引用給你,并記錄到池里。

      • 這樣相同的字符串字面量只存一份,省內存。

    • intern()方法: 可以將一個字符串對象動態地放入常量池(如果池中沒有),并返回池中對象的引用。

  • 經典面試題:String s = new String("abc"); 創建了幾個對象?

    1. "abc"是個字面量。JVM先去字符串常量池找:

      • 如果池里沒有:在堆里的常量池區域創建一個"abc"對象 (1個)。

      • 無論池里有沒有"abc"new String(...)都會在堆里(常量池區域之外)創建一個全新的String對象 (另1個),這個新對象的內容(char[])指向常量池里的"abc"char[](或拷貝一份,取決于JVM實現)。

    2. 變量s(存的是堆里新對象的地址)存在里。

    • 結論: 總是創建至少1個堆對象(new出來的那個)。如果常量池原本沒有"abc",則總共創建2個對象(1個在池里,1個是new出來的);如果常量池已有"abc",則總共創建1個對象(只有new出來的那個)。

5. 引用類型有哪幾種?強弱分明!

Java里有4種引用強度,決定了對象被GC回收的優先級:

5.1 強引用 (Strong Reference) - “鐵哥們”

  • 最常見!

Object obj = new Object(); 這種就是。
  • 特點: 只要強引用還在(并且可達),GC絕不會回收這個對象。它是對象存活的最強保證obj = null;后,對象就變不可達(如果沒其他引用),可被回收。

5.2 軟引用 (Soft Reference) - “好朋友”

  • 代表: java.lang.ref.SoftReference

  • 特點: 描述一些還有用但非必需的對象(比如緩存)。只有在系統內存快不夠用,要發生OOM之前,GC才會回收它們。適合做緩存(內存不足時自動清理)。SoftReference.get() 可能返回 null

5.3 弱引用 (Weak Reference) - “點頭之交”

  • 代表: java.lang.ref.WeakReference

  • 特點: 強度比軟引用更弱。下一次GC發生時(無論Minor還是Full GC),不管當前內存是否充足,都會回收只被弱引用關聯的對象。適合做緩存避免內存泄漏(比如WeakHashMap的key)。WeakReference.get() 可能在GC后返回 null

  • 舉個栗子:弱引用緩存 (優化版,強調檢查null)

    import java.lang.ref.WeakReference;
    import java.util.HashMap;
    import java.util.Map;
    ?
    public class YA33CacheExample {
    ?private Map<String, WeakReference<MyHeavyObject>> cache = new HashMap<>();
    ?public MyHeavyObject get(String key) {// 1. 從緩存拿弱引用WeakReference<MyHeavyObject> ref = cache.get(key);// 2. 關鍵!弱引用可能還在Map里,但對象可能已被GC回收,所以要用get()取對象MyHeavyObject obj = (ref != null) ? ref.get() : null;
    ?// 3. 如果對象是null(被回收了或第一次訪問)if (obj == null) {obj = createExpensiveObject(key); // 創建代價高的大對象cache.put(key, new WeakReference<>(obj)); // 用弱引用包裝后放入緩存}return obj;}
    ?private MyHeavyObject createExpensiveObject(String key) {// 模擬創建一個大對象或耗時操作return new MyHeavyObject();}
    ?private static class MyHeavyObject {private byte[] largeData = new byte[1024 * 1024 * 10]; // 10MB數據}
    }
    • WeakReference包裝大對象放入緩存。

    • 當內存吃緊時,GC會自動回收這些只被弱引用指向的大對象。

    • 關鍵點: 下次get一定要檢查ref.get()是否為null! 如果為null,說明對象已被GC回收,需要重新創建并緩存。

5.4 虛引用 (Phantom Reference) - “影子朋友”

  • 代表: java.lang.ref.PhantomReference (必須配合ReferenceQueue使用)

  • 特點: 最弱的引用。一個對象是否有虛引用,完全不影響它啥時被回收。你無法通過虛引用拿到對象本身(get()總是返回null)。

  • 唯一作用: 對象被GC回收時,你能收到一個通知(通過ReferenceQueue)。常用于精細化管理堆外內存(比如NIO的DirectByteBuffer),確保在回收Java對象時同步釋放關聯的本地內存,防止內存泄漏。PhantomReference 入隊發生在對象被完全回收(finalized)之后

6. 內存泄漏 vs 內存溢出 (OOM)

6.1 內存泄漏 (Memory Leak) - “垃圾占著地方不走”

  • 定義: 程序中的對象已經不再使用了,但因為某些原因(比如還被意外的引用著)無法被垃圾回收(GC)回收。這些“垃圾”占著內存不釋放,導致可用內存越來越少

  • 后果: 長期累積,最終可能觸發內存溢出(OOM),程序崩潰。

  • 常見原因:

    • 靜態集合濫用:staticHashMap, ArrayList等長期持有對象引用不放(尤其是集合只增不減時)。

    • 未關閉資源: 數據庫連接(Connection)、文件流(InputStream/OutputStream)、網絡連接(Socket)、SwingGraphics對象等打開后忘記關閉(或close()沒執行到)。

    • 監聽器未注銷: 注冊了事件監聽器,對象不用了卻沒取消注冊,導致被事件源長期引用。

    • ThreadLocal使用不當: 用完沒調用remove()清理,尤其在線程池(線程復用)場景,會導致線程的ThreadLocalMap中該Entry的value無法釋放(雖然key是弱引用會回收,但value是強引用)。

    • 內部類持有外部類: 非靜態內部類實例會隱式持有外部類實例的強引用。如果外部類實例本應回收,但內部類實例還被其他地方引用著,就會導致外部類泄漏。

    • 緩存未清理: 使用緩存(如Map)時,對象不再使用但未從緩存中移除。

6.2 內存溢出 (OutOfMemoryError, OOM) - “地方實在不夠用了”

  • 定義: JVM在申請內存時,沒有足夠的空間來創建新對象了,并且經過垃圾回收后仍然無法獲得足夠空間,JVM就會拋出OutOfMemoryError錯誤。

  • 常見類型 & 原因:

    • java.lang.OutOfMemoryError: Java heap space堆內存真不夠了。原因:創建太多對象、嚴重內存泄漏、配置堆太小(-Xmx設小了)、加載超大文件到內存。

    • java.lang.OutOfMemoryError: Metaspace元空間(存類信息)不夠了。原因:加載了海量類(大量反射、動態代理、CGLib/ASM生成類、OSGi應用)。

    • java.lang.OutOfMemoryError: Direct buffer memory直接內存不夠了。原因:NIO操作申請太多DirectByteBuffer沒釋放(或GC沒觸發Cleaner)或-XX:MaxDirectMemorySize設小了。

    • java.lang.OutOfMemoryError: unable to create new native thread:創建線程需要的棧空間不夠了。原因:線程創建太多(-Xss設太大或系統限制)、進程地址空間耗盡(32位系統)。

    • java.lang.OutOfMemoryError: Requested array size exceeds VM limit:嘗試分配一個超過堆限制的數組(如Integer.MAX_VALUE)。

    • java.lang.StackOverflowError:通常是虛擬機棧或本地方法棧溢出。原因:方法調用太深(無限遞歸最常見)、棧幀過大(局部變量太多或太大)。(嚴格來說屬于Error,但常與OOM一起討論)

  • 關系: 長期嚴重的內存泄漏必然導致內存溢出(OOM)。但OOM也可能是瞬間需要的內存確實超過了JVM配置的最大值(如加載一個超大文件),不一定是泄漏。StackOverflowError通常不是內存泄漏引起。

7. 類加載過程 - 從.class文件到可用類

類需要被加載到JVM才能使用。這個過程分幾步走:

加載 (Loading):

找到.class文件(文件系統、網絡、JAR包等),讀入二進制數據,在方法區創建代表這個類的java.lang.Class對象(作為訪問入口)。

  1. 鏈接 (Linking): 分三步:

    • 驗證 (Verification): 檢查.class文件格式對不對(魔數、版本),字節碼合不合法(指令、跳轉),符號引用是否有效,是否符合語言安全約束。防止有害字節碼。

    • 準備 (Preparation):的靜態變量(static)分配內存(在方法區),并設置默認初始值(如int是0,booleanfalse,對象引用是null)。注意:final static常量(編譯期常量)這里就賦值了。

    • 解析 (Resolution): 把類、方法、字段的符號引用(常量池中的名字)變成具體的直接引用(內存地址或偏移量)。解析可能在初始化前發生,也可能延遲到首次使用時(如invokedynamic)。

  2. 初始化 (Initialization): 執行類的構造器<clinit>()方法(編譯器自動收集所有static變量賦值和static{}塊生成)。給靜態變量賦程序員寫的初始值父類先初始化。初始化是類加載的最后一步,也是真正執行類中Java代碼的開始。

8. 雙親委派模型 - “孩子有事先找爹”

類加載器有層級關系(像家族):

  1. 啟動類加載器 (Bootstrap ClassLoader): 頂級大佬(通常C++實現),加載JAVA_HOME/lib目錄下的核心庫(如rt.jar, charsets.jar)。

  2. 擴展類加載器 (Extension ClassLoader): 繼承自java.lang.ClassLoader(Java實現),加載JAVA_HOME/lib/ext目錄或java.ext.dirs系統變量指定目錄的jar包。

  3. 應用程序類加載器 (Application ClassLoader / System ClassLoader): 繼承自java.lang.ClassLoader(Java實現),加載用戶程序ClassPath-cp-classpath指定)下的類。我們平時默認用的就是它

  4. 自定義類加載器 (Custom ClassLoader): 用戶自己寫的加載器,繼承java.lang.ClassLoader。可定制加載來源(網絡、加密文件等)。

  5. tomcat類加載器:tomcat自定義的加載器

雙親委派原則:

  • 當一個類加載器收到加載請求時,先不自己加載,而是遞歸地委托給父加載器去嘗試加載。

  • 只有當所有父加載器都表示找不到這個類時(在自己的加載路徑下找不到),子加載器才會自己嘗試加載

好處:

  • 安全: 防止用戶寫個java.lang.Objectjava.lang.String類覆蓋核心庫的(父加載器會先加載到核心的)。

  • 避免重復: 保證同一個類(由同一個類加載器加載)只被加載一次。

破壞雙親委派:

  • 歷史原因: JDK1.2引入雙親委派之前的老代碼(如ClassLoaderfindClass()方法)。

  • SPI (Service Provider Interface): 如JDBC驅動。核心接口在rt.jar(由Bootstrap加載),但實現類(驅動)在ClassPath下。需要線程上下文類加載器(Thread Context ClassLoader)來加載。

  • 熱部署/熱替換: OSGi、Tomcat等容器需要動態加載、卸載模塊,需要自定義類加載器并打破委派。

  • 隔離: 同一個應用加載不同版本庫(如不同Web應用加載不同Spring版本),需要各自獨立的類加載器。

9. 垃圾回收 (GC) - JVM的自動清潔工

9.1 什么是GC?

GC就是JVM自動回收不再使用(不可達)的對象所占用的內存,避免內存泄漏和手動管理的麻煩。

9.2 怎么判斷對象是垃圾?

主流用 可達性分析算法 (Reachability Analysis)

  • 從一組 “GC Roots” 對象(根對象集合)出發。GC Roots包括:

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

    • 方法區中類靜態屬性(static)引用的對象。

    • 方法區中常量(final static)引用的對象。

    • 本地方法棧中JNI(即native方法)引用的對象(全局引用)。

    • Java虛擬機內部的引用(如基本類型對應的Class對象,常駐異常對象NullPointerException等)。

    • 所有被同步鎖(synchronized)持有的對象。

  • 看哪些對象能被這些根對象直接或間接引用到(形成引用鏈)。

  • 如果一個對象到GC Roots沒有任何引用鏈相連,它就是不可達的,是垃圾,可以被回收。

9.3 垃圾回收算法 - 清潔工的打掃方式

  • 標記-清除 (Mark-Sweep):

    • 步驟:先標記垃圾 -> 直接清除。

    • 缺點: 效率不高(掃描+清除),產生內存碎片(不連續空間)。

  • 復制 (Copying):

    • 步驟:把內存分兩塊(A/B),只用A。A滿了,把A里活著的對象復制到B,清空A。下次用B。

    • 優點: 無碎片,分配快(順序分配)。

    • 缺點: 浪費一半內存。存活對象多時效率低。

    • 適用: 新生代(存活對象少)。

  • 標記-整理 (Mark-Compact):

    • 步驟:先標記垃圾 -> 讓所有活著的對象向一端“搬家” -> 清理邊界外空間。

    • 優點: 無碎片,內存利用率高。

    • 缺點: “搬家”開銷大。

    • 適用: 老年代

  • 分代收集 (Generational Collection): 最常用策略!

    • 核心思想:根據對象存活周期不同,將堆劃分為新生代(Young)和老年代(Old)。

    • 新生代: 對象“朝生夕死”,回收頻繁。采用復制算法(Eden + 2x Survivor)。

    • 老年代: 對象存活時間長。采用標記-清除標記-整理算法。

    • 對象晉升: 新生代對象熬過一定次數(默認15)GC后,晉升到老年代。大對象也可能直接進老年代。

9.4 垃圾回收器 - 不同的清潔工團隊 (簡要概述主流)

  • Serial / Serial Old: 單線程,簡單高效(無并發開銷),適合Client模式或小內存。

  • ParNew: Serial的多線程版(新生代并行),需配合CMS使用。

  • Parallel Scavenge / Parallel Old: JDK8默認組合。關注吞吐量(Throughput = 用戶代碼時間 / (用戶代碼時間 + GC時間))。適合后臺計算。

  • CMS (Concurrent Mark-Sweep): (JDK14廢棄) 老年代收集器,目標是減少停頓時間。采用“標記-清除”,過程復雜(初始標記->并發標記->重新標記->并發清除)。有碎片問題,并發階段占用CPU。

  • G1 (Garbage-First): JDK9+默認! 將堆分成多個大小相等的Region(物理不連續),可預測停頓時間模型。采用“標記-整理”算法。特點:整體看是“標記-整理”,局部(Survivor->Survivor/Survivor->Old)看是“復制”。兼顧吞吐量和低延遲,適合大堆。無碎片。

  • ZGC: JDK15+生產可用。追求超低停頓(<10ms),適合超大堆(TB級)。采用染色指針、讀屏障等技術。不分代(邏輯分代)。

  • Shenandoah: OpenJDK提供,類似ZGC,低停頓目標。采用Brooks指針、讀/寫屏障。不分代(邏輯分代)。

9.5 Minor GC / Major GC / Full GC - 清潔范圍不同

類型打掃范圍觸發條件特點常用算法 (分代)
Minor GC (Young GC)只掃新生代 (Eden + Survivor)Eden區滿了頻繁,快,停頓短復制 (Eden -> S, S間復制)
Major GC (Old GC)主要掃老年代 (通常伴隨一次Minor GC)老年代滿了 / 根據策略(如CMS閾值) / 對象晉升太快失敗較少,較慢,停頓較長標記-清除 / 標記-整理
Full GC掃整個堆 + 元空間 (可能包含永久代/壓縮堆)1. 老年代滿且Major GC搞不定 2. 元空間滿 3. System.gc()調用 (建議-XX:+DisableExplicitGC禁用) 4. 堆空間擔保失敗 5. CMS并發失敗 6. JVM自身策略(如HeapDumpOnOutOfMemoryError前)最慢!停頓最長!盡量避免!取決于老年代/整堆收集器設置

9.6 Stop-The-World (STW) - “世界暫停”/

  • GC進行某些關鍵步驟時(比如枚舉GC Roots、對象標記階段的部分過程、對象移動),為了保證結果的準確性(對象引用關系不變)和安全性,必須暫停所有應用線程,就像全世界都停止了。

  • 這是GC產生停頓的主要原因。優化GC的核心目標之一就是減少STW的時間和頻率。像CMS、G1、ZGC、Shenandoah都在努力通過并發(應用線程和GC線程同時運行)來減少STW。

10. GC不止掃堆!

JVM的垃圾回收器主要清理堆里的對象垃圾,但也會清理方法區(元空間)!它會清理不再使用的類信息(類卸載)、廢棄的常量等。類卸載條件苛刻(類ClassLoader被回收、類所有實例被回收、類Class對象沒被引用)。元空間的垃圾回收通常由Full GC觸發。

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

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

相關文章

計算機網絡:什么是AD域

什么是AD域? AD域(Active Directory Domain)是微軟基于Active Directory(活動目錄) 技術構建的網絡管理架構,用于集中管理網絡中的用戶、計算機、設備、權限等資源。它是企業級網絡環境中實現身份認證、資源共享和安全控制的核心組件。 AD域的核心功能與作用 集中化身份…

虛幻基礎:場景位置相對位置

能幫到你的話&#xff0c;就給個贊吧 &#x1f618; 文章目錄絕對坐標&#xff1a;絕對坐標不會改變絕對坐標絕對方向x&#xff1a;世界的前y&#xff1a;世界的右z&#xff1a;世界的上相對坐標&#xff1a;坐標系的原點和方向會基于父組件 變換相對坐標相對方向&#xff1a;改…

【代碼隨想錄day 16】 力扣 106.從中序與后序遍歷序列構造二叉樹

視頻講解&#xff1a;https://www.bilibili.com/video/BV1vW4y1i7dn/?vd_sourcea935eaede74a204ec74fd041b917810c 文檔講解&#xff1a;https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E…

vue+flask大模型寫詩詩詞推薦與可視化系統

文章結尾部分有CSDN官方提供的學長 聯系方式名片文章結尾部分有CSDN官方提供的學長 聯系方式名片關注B站&#xff0c;有好處&#xff01;編號&#xff1a; F061 大模型詩詞推薦與可視化系統 在傳統文化數字化的浪潮下&#xff0c;我開發了這款詩歌問答大數據平臺&#xff0c;旨…

Apache Ignite 核心組件:GridClosureProcessor解析

這是一個 Apache Ignite 中非常核心的組件 —— GridClosureProcessor&#xff0c;它是 分布式閉包&#xff08;Closure&#xff09;執行的調度中樞&#xff0c;負責在集群節點上異步執行用戶提交的任務&#xff08;如 Runnable、Closure&#xff09;。 我們來逐層深入理解它的…

for循環詳解與實戰技巧

目錄 一、for循環語法 二、for循環執行流程 流程圖表示&#xff1a; 三、for循環實踐示例 示例&#xff1a;在屏幕上打印1~10的值 四、while循環與for循環對比 for循環和while循環都包含三個關鍵部分&#xff1a; 兩者的主要區別在于代碼組織方式&#xff1a; 五、練習…

winform中的listbox實現拖拽功能

文章目錄前言一、實現前言 winform中的listBox實現拖拽&#xff01; 一、實現 winform中的listbox實現拖拽只需要實現四個事件 1、準備兩個listbox控件 其中listtarget&#xff0c;AllowDrop屬性設置為True。 2、實現四個事件 2.1MouseDown //在 MouseDown 事件期間&#x…

用 Docker 安裝并啟動 Redis:從入門到實戰

用 Docker 安裝并啟動 Redis&#xff1a;從入門到實戰Redis 作為一款高性能的鍵值對數據庫&#xff0c;在緩存、會話存儲、消息隊列等場景中被廣泛應用。本文將詳細介紹如何使用 Docker 快速安裝和啟動 Redis&#xff0c;包括基礎配置、數據持久化以及容器管理等核心操作&#…

ansible學習第一天

一&#xff1a;ansible基礎知識1.1 ansible的定義與工作原理簡述ansible是一個自動化運維工具&#xff0c;用于執行自動化任務&#xff0c;包括像配置管理&#xff0c;應用部署&#xff0c;任務執行等等&#xff0c;本質上來說也是基礎設施及代碼工具&#xff0c;通過可讀性較強…

Vue原理與高級開發技巧詳解

Vue 的底層原理、高級用法、性能優化和生態整合 文章目錄Vue 的底層原理、高級用法、性能優化和生態整合一、Vue 雙向綁定原理深度剖析1. Vue 2 實現原理&#xff08;Object.defineProperty&#xff09;2. Vue 3 實現原理&#xff08;Proxy&#xff09;3. v-model 高級用法二、…

axios的封裝

axios的封裝 在src目錄下新建文件夾utils工具類&#xff0c;文件夾里面新建http.js文件&#xff0c;如果項目涉及到多個基地址可以新建http2.js文件。 import axios from axios;/*** 后端*/// 創建axios實例 const http axios.create({// 1.接口基地址baseURL: http://192.168…

MariaDB 數據庫管理與web服務器

MariaDB 數據庫管理與WEB 服務器 介紹 MariaDB 數據庫介紹 **數據庫&#xff0c;是一個存放計算機數據的倉庫。**這個倉庫是按照一定的數據結構來對數據進行組織和存儲的&#xff0c;我們可以通過數據庫提供的多種方法來管理其中的數據。 數據結構&#xff0c;是指數據的組織形…

分治-歸并-912.排序數組-力扣(LeetCode)

一、題目解析1、將數組排升序2、在不使用任何內置函數的情況下解決問題二、算法原理分治-歸并合并兩個有序數組1、雙指針遍歷兩個合并數組2、將比較后的較小值放到新開數組中3、防止有指針未遍歷完&#xff0c;特殊處理4、將nums中的元素還原三、代碼示例vector<int> tmp…

網絡安全初學者學習心得

看到你對網絡安全學習的興趣&#xff0c;我感到非常振奮&#xff01;這個領域既充滿挑戰又回報豐厚&#xff0c;作為初學者&#xff0c;理清學習內容和方向確實至關重要。下面我將結合多年的行業觀察和指導經驗&#xff0c;為你詳細拆解網絡安全初學者的學習內容并分享一些核心…

防火墻筆記優化版

一、防火墻的核心定義防火墻是一種基于預設安全策略&#xff0c;用于隔離內網與外網、控制網絡流量的安全系統&#xff08;可分為軟件系統或硬件系統&#xff09;。其核心作用包括&#xff1a;流量隔離&#xff1a;物理或邏輯分隔內網、外網及 DMZ 區域&#xff08;DMZ 為內網與…

vue3前端項目cursor rule

cursor rule是什么&#xff0c;以及怎么定義&#xff0c;看這個文章&#xff1a; cursor中定義cursor rules_cursor rules如何編寫-CSDN博客 針對現有一個vue3的前端項目&#xff0c;寫了一份cursor rule&#xff0c;可以作為參考&#xff0c;內容如下&#xff08;僅作為參考&…

基于51單片機紅外遙控定時開關智能家電插座設計

1. 功能介紹 本設計是一款基于 STC8C52 單片機 的智能家電插座系統&#xff0c;集 紅外遙控控制、定時開關控制、自動與手動模式切換、掉電數據保存、液晶顯示、蜂鳴器提示 于一體&#xff0c;能夠方便用戶對家用電器進行精準的定時控制與遠程操作。系統廣泛適用于家用電器、辦…

下一代防火墻組網方案

知識回顧&#xff1a;1.傳統防火墻包括包過濾防火墻、應用網關防火墻、狀態檢測防火墻。2.包過濾防火墻工作在3、4層。3.包過濾防火墻特點&#xff1a;4.應用網關防火墻主要作用&#xff1a;①截取用戶初始化連接請求&#xff0c;對用戶進行認證&#xff1b;②通過ALG能讓多通道…

WEB開發-第二十七天(PHP篇)

DW PHPStorm PhpStudy Navicat Premium DW : HTML&JS&CSS開發 PHPStorm : 專業PHP開發IDE PhpStudy &#xff1a;Apache MYSQL環境 Navicat Premium: 全能數據庫管理工 變量覆蓋安全&#xff1a; $GLOBALS&#xff1a;這種全局變量用于在PHP腳本中的任意位置訪…

Lwip深度閱讀-網絡架構

LWIP網絡協議棧詳細介紹 本文的內容基本基于野火的LWIP手冊&#xff0c;和LWIP源碼撰寫。 網絡協議棧概述 從圖片可以看出&#xff0c;網絡協議棧采用分層架構&#xff0c;每一層都有特定的功能和協議。 TCP/IP協議分層模型數據封裝過程MAC數據包 我使用wireShark抓包的時候&am…