深入理解Java虛擬機(JVM):從內存管理到性能優化

深入理解Java虛擬機(JVM):從內存管理到性能優化

目錄

  • 引言
  • JVM架構概述
    • 1. 類加載器(Class Loader)
    • 2. 運行時數據區(Runtime Data Areas)
    • 3. 執行引擎(Execution Engine)
    • 4. 本地方法接口(Native Method Interface)
    • 5. 本地方法庫(Native Method Libraries)
  • 內存管理
    • 1. 運行時數據區詳解
    • 2. 垃圾回收機制(Garbage Collection)
      • 2.1 如何判斷對象是否“已死”
      • 2.2 垃圾回收算法
      • 2.3 垃圾收集器
    • 3. 內存分配與回收策略
  • 性能優化
    • 1. JVM參數調優
    • 2. 常見性能問題及排查
    • 3. 監控工具
  • 代碼示例:演示內存分配和GC過程
  • 總結與展望

引言

Java作為一門廣泛應用于企業級開發、移動應用、大數據等領域的編程語言,其強大的跨平臺特性離不開Java虛擬機(JVM)的支持。JVM是Java程序的運行環境,它負責將Java字節碼翻譯成機器碼并執行,同時還承擔著內存管理、垃圾回收、性能優化等核心職責。對于Java開發者而言,深入理解JVM的工作原理,不僅能夠幫助我們編寫出更高效、更穩定的代碼,還能在遇到性能瓶頸時,快速定位并解決問題。

本文將帶您深入探索JVM的奧秘,從其架構設計、內存管理機制,到垃圾回收原理,再到性能調優實踐,旨在為您構建一個全面而深入的JVM知識體系。無論您是Java初學者,還是經驗豐富的資深開發者,相信本文都能為您帶來新的啟發和收獲。

JVM架構概述

Java虛擬機(JVM)是一個抽象的計算機,它提供了一個運行時環境,使得Java程序可以在任何支持JVM的硬件平臺上運行。JVM的架構主要由以下幾個部分組成:

1. 類加載器(Class Loader)

類加載器子系統負責從文件系統或網絡中加載Java類的字節碼,并將其加載到JVM內存中。它遵循“雙親委派模型”,確保Java核心庫的類型安全。類加載過程包括加載、驗證、準備、解析和初始化五個階段。

2. 運行時數據區(Runtime Data Areas)

運行時數據區是JVM在執行Java程序時所管理的內存區域,它被劃分為幾個不同的部分,用于存儲程序執行期間的各種數據。這些區域有的隨著虛擬機啟動而存在,有的則隨著線程的生命周期而創建和銷毀。主要包括:

  • 程序計數器(Program Counter Register):一塊較小的內存空間,用于存儲當前線程所執行的字節碼的行號指示器。它是線程私有的,每個線程都有一個獨立的程序計數器。
  • Java虛擬機棧(Java Virtual Machine Stacks):線程私有的,每個方法執行時都會創建一個棧幀,用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。方法的調用和執行過程對應著棧幀在虛擬機棧中的入棧和出棧。
  • 本地方法棧(Native Method Stacks):與虛擬機棧類似,但它為JVM執行Native方法(即用C/C++等語言編寫的方法)服務。
  • Java堆(Java Heap):JVM所管理的內存中最大的一塊,被所有線程共享。幾乎所有的對象實例和數組都在這里分配內存。Java堆是垃圾回收器管理的主要區域。
  • 方法區(Method Area):線程共享的內存區域,用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。在JDK 8及以后版本,方法區被元空間(Metaspace)取代,元空間使用本地內存,而不是JVM內存。

3. 執行引擎(Execution Engine)

執行引擎負責執行Java字節碼。它可以通過解釋執行(Interpreter)或即時編譯(JIT Compiler)兩種方式來執行字節碼。解釋器逐行解釋執行字節碼,而JIT編譯器則將熱點代碼編譯成機器碼,提高執行效率。

4. 本地方法接口(Native Method Interface)

本地方法接口允許Java代碼調用非Java語言編寫的本地庫(如C/C++)。通過JNI(Java Native Interface),Java程序可以與底層操作系統或硬件進行交互。

5. 本地方法庫(Native Method Libraries)

本地方法庫是執行引擎調用本地方法時所依賴的本地代碼庫。
在這里插入圖片描述

內存管理

Java虛擬機的內存管理是其核心功能之一,它負責為對象分配內存,并在對象不再被引用時自動回收內存。理解JVM的內存管理機制對于避免內存泄漏、優化程序性能至關重要。

1. 運行時數據區詳解

前面我們已經概括性地介紹了JVM的運行時數據區,這里我們將對其進行更詳細的闡述,特別是與內存管理密切相關的Java堆和方法區。
在這里插入圖片描述

  • 程序計數器(Program Counter Register):這是JVM中唯一一個不會出現OutOfMemoryError的區域。它記錄了當前線程正在執行的字節碼指令的地址。如果當前線程正在執行的是Native方法,則這個計數器值為空。

  • Java虛擬機棧(Java Virtual Machine Stacks):每個方法在執行的同時都會創建一個棧幀(Stack Frame)用于存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每個方法從調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中入棧到出棧的過程。局部變量表存放了編譯期可知的各種基本數據類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,它不等同于對象本身,可能是一個指向對象起始地址的引用指針,也可能是指向一個代表對象的句柄或其他與此對象相關的位置)和returnAddress類型(指向了一條字節碼指令的地址)。

  • 本地方法棧(Native Method Stacks):與虛擬機棧類似,但它為Native方法服務。當Java程序調用Native方法時,JVM會為該Native方法創建一個本地方法棧幀,并將其壓入本地方法棧。如果本地方法棧深度溢出,也會拋出StackOverflowError

  • Java堆(Java Heap):Java堆是JVM所管理的內存中最大的一塊,也是垃圾回收器管理的主要區域。幾乎所有的對象實例以及數組都在這里分配內存。Java堆是所有線程共享的,因此在多線程環境下,需要考慮線程安全問題。Java堆可以細分為:

    • 新生代(Young Generation):新創建的對象通常在這里分配內存。新生代又分為一個Eden區和兩個Survivor區(From Survivor和To Survivor)。大多數對象在Eden區中創建,當Eden區滿時,會觸發一次Minor GC,存活的對象會被移動到Survivor區。經過多次Minor GC后仍然存活的對象,會被移動到老年代。
    • 老年代(Old Generation):用于存放新生代中經歷多次垃圾回收仍然存活的對象,或者是一些較大的對象(例如大數組)。老年代的垃圾回收通常稱為Major GC或Full GC,其頻率較低,但耗時較長。
  • 方法區(Method Area):方法區是用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。它也是線程共享的。在JDK 8及以后版本,方法區被元空間(Metaspace)取代。元空間與永久代(PermGen)最大的區別在于,元空間使用的是本地內存,而不是JVM內存,因此默認情況下,元空間的大小只受限于本地內存的大小,避免了OutOfMemoryError的風險。

2. 垃圾回收機制(Garbage Collection)

垃圾回收(GC)是Java自動內存管理的核心。當Java堆中的對象不再被引用時,垃圾回收器會自動回收這些對象所占用的內存空間,從而避免內存泄漏和內存溢出。GC主要關注堆和方法區。

2.1 如何判斷對象是否“已死”

在進行垃圾回收之前,JVM需要判斷哪些對象是“活”的,哪些是“死”的。主要有兩種算法:

  • 引用計數算法(Reference Counting):為每個對象維護一個引用計數器,當對象被引用時計數器加1,引用失效時計數器減1。當計數器為0時,表示對象可以被回收。然而,該算法無法解決循環引用問題,因此Java虛擬機并沒有采用此算法。
  • 可達性分析算法(Reachability Analysis):通過一系列稱為“GC Roots”的對象作為起始點,從這些節點向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain)。當一個對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的。GC Roots包括:虛擬機棧中引用的對象、本地方法棧中引用的對象、方法區中靜態屬性引用的對象、方法區中常量引用的對象等。
2.2 垃圾回收算法
  • 標記-清除算法(Mark-Sweep):分為“標記”和“清除”兩個階段。首先標記出所有需要回收的對象,然后統一回收所有被標記的對象。缺點是效率不高,并且會產生大量不連續的內存碎片。

  • 復制算法(Copying):將可用內存劃分為大小相等的兩塊,每次只使用其中一塊。當這一塊內存用完時,就將還存活著的對象復制到另一塊上面,然后再把已使用過的內存空間一次清理掉。優點是效率高,不會產生內存碎片。缺點是內存利用率低,只適用于新生代。

  • 標記-整理算法(Mark-Compact):結合了標記-清除和復制算法的優點。首先標記出所有存活的對象,然后將所有存活的對象都向一端移動,最后直接清理掉端邊界以外的內存。解決了內存碎片問題,但效率相對較低。

  • 分代收集算法(Generational Collection):根據對象的生命周期將Java堆劃分為新生代和老年代,并根據不同代的特點采用不同的垃圾回收算法。新生代中對象存活率低,適合使用復制算法;老年代中對象存活率高,適合使用標記-整理或標記-清除算法。

2.3 垃圾收集器

JVM提供了多種垃圾收集器,它們是垃圾回收算法的具體實現。常見的垃圾收集器包括:

  • Serial收集器:單線程的收集器,進行垃圾回收時必須暫停所有用戶線程(“Stop The World”)。適用于小型應用或客戶端模式。
  • ParNew收集器:Serial收集器的多線程版本,用于新生代。同樣會“Stop The World”。
  • Parallel Scavenge收集器:吞吐量優先的收集器,用于新生代。它關注的是達到一個可控制的吞吐量(CPU用于運行用戶代碼的時間與CPU總消耗時間的比值)。
  • CMS(Concurrent Mark Sweep)收集器:以獲取最短回收停頓時間為目標的收集器,用于老年代。它采用標記-清除算法,分四個步驟:初始標記、并發標記、重新標記、并發清除。其中并發標記和并發清除階段可以與用戶線程并發執行,減少停頓時間。
  • G1(Garbage-First)收集器:面向服務端應用的垃圾收集器,JDK 7及以后版本提供。它將Java堆劃分為多個大小相等的獨立區域(Region),每個Region都可以根據需要扮演新生代的Eden、Survivor或者老年代的角色。G1收集器在停頓時間上做了很多優化,可以預測停頓時間,并且在回收時優先回收垃圾最多的區域。

在這里插入圖片描述

3. 內存分配與回收策略

Java對象的內存分配主要在堆上進行,其分配策略包括:

  • 對象優先在Eden區分配:大多數情況下,對象在新生代的Eden區中分配。當Eden區空間不足時,會發起一次Minor GC。
  • 大對象直接進入老年代:需要大量連續內存空間的Java對象(如很長的字符串或大數組)會直接在老年代中分配,避免在Eden區及兩個Survivor區之間來回復制,從而提高效率。
  • 長期存活的對象進入老年代:在新生代中經歷過多次(默認15次)Minor GC仍然存活的對象,會被移動到老年代。
  • 空間分配擔保:在發生Minor GC之前,JVM會檢查老年代最大可用的連續空間是否大于新生代所有對象總空間。如果大于,則Minor GC可以確保是安全的。如果小于,則JVM會查看HandlePromotionFailure設置是否允許擔保失敗。如果允許,則會檢查老年代最大可用的連續空間是否大于歷次晉升到老年代對象的平均大小。如果大于,則嘗試進行一次Minor GC,但這次Minor GC是有風險的。如果小于或不允許擔保失敗,則會進行一次Full GC。

性能優化

JVM性能優化是Java應用開發中不可或缺的一環。通過合理的JVM參數配置和對應用程序的優化,可以顯著提升應用的性能、穩定性和資源利用率。

1. JVM參數調優

JVM參數調優是性能優化的重要手段。以下是一些常用的JVM參數及其調優建議:

  • 堆大小設置

    • -Xms<size>:設置JVM初始堆內存大小。建議與-Xmx設置相同,避免運行時動態調整堆大小帶來的性能開銷。
    • -Xmx<size>:設置JVM最大堆內存大小。根據應用的需求和服務器的物理內存大小進行設置。過小可能導致頻繁GC和OutOfMemoryError,過大可能導致GC時間過長。
    • -Xmn<size>:設置新生代大小。新生代過小會導致Minor GC頻繁,過大則可能導致老年代空間不足。
    • -XX:NewRatio=<ratio>:設置新生代與老年代的比例。例如,-XX:NewRatio=2表示新生代與老年代的比例為1:2,即新生代占整個堆的1/3。
    • -XX:SurvivorRatio=<ratio>:設置Eden區與Survivor區的比例。例如,-XX:SurvivorRatio=8表示Eden區與每個Survivor區的比例為8:1,即Eden區占新生代的8/10。
  • 垃圾收集器選擇

    • -XX:+UseSerialGC:使用Serial收集器(新生代和老年代都使用)。
    • -XX:+UseParNewGC:使用ParNew收集器(新生代),配合CMS或Serial Old(老年代)。
    • -XX:+UseParallelGC:使用Parallel Scavenge收集器(新生代),配合Parallel Old(老年代)。
    • -XX:+UseConcMarkSweepGC:使用CMS收集器(老年代),配合ParNew(新生代)。
    • -XX:+UseG1GC:使用G1收集器。G1是JDK 7及以后版本推薦的收集器,適用于大內存多核服務器。
  • GC日志分析

    • -XX:+PrintGCDetails:打印詳細的GC日志。
    • -XX:+PrintGCDateStamps:在GC日志中打印時間戳。
    • -Xloggc:<file_path>:將GC日志輸出到指定文件。
      通過分析GC日志,可以了解GC的頻率、停頓時間、內存回收量等信息,從而判斷GC是否成為性能瓶頸。

2. 常見性能問題及排查

  • 內存泄漏(Memory Leak):指程序中已不再使用的對象仍然被引用,導致垃圾回收器無法回收其占用的內存,最終導致內存溢出。常見原因包括:靜態集合類引用對象、監聽器和回調、線程池未關閉等。排查工具可以使用JProfiler、VisualVM等。
  • CPU占用過高:可能是由于死循環、頻繁的線程上下文切換、不合理的并發編程、大量計算等導致。可以通過jstack查看線程堆棧,top命令查看CPU占用高的進程,再結合jstatjmap等工具進行分析。
  • 頻繁GC:通常是由于堆內存設置不合理、對象創建過于頻繁、存在大量臨時對象等導致。可以通過調整堆大小、優化代碼減少對象創建、使用對象池等方式解決。

3. 監控工具

  • JConsole:JDK自帶的圖形化監控工具,可以用于監控JVM內存、線程、類加載等信息,并進行簡單的MBeans操作。
  • VisualVM:JDK自帶的更強大的圖形化監控工具,集成了JConsole、JStack、JMap等功能,可以進行CPU、內存、線程分析,并支持插件擴展。
  • JProfiler:商業化的Java性能分析工具,功能強大,可以進行內存分析、CPU分析、線程分析、數據庫分析等,提供豐富的圖表和報告。
  • Arthas:阿里巴巴開源的Java診斷工具,可以在線排查問題,無需重啟JVM,支持查看JVM運行狀態、類加載信息、方法執行耗時等。

代碼示例:演示內存分配和GC過程

為了更好地理解JVM的內存分配和垃圾回收過程,我們來看一個簡單的Java代碼示例。這個示例將模擬大量對象的創建,并觀察垃圾回收的行為。

import java.util.ArrayList;
import java.util.List;public class GcExample {public static void main(String[] args) throws InterruptedException {System.out.println("JVM內存分配與GC示例啟動...");List<Object> list = new ArrayList<>();int count = 0;try {while (true) {// 每次循環創建1MB大小的字節數組byte[] data = new byte[1024 * 1024]; list.add(data);count++;if (count % 100 == 0) {System.out.println("已創建 " + count + " MB對象");// 模擬業務邏輯,讓部分對象有機會被回收Thread.sleep(100);}// 模擬內存溢出,當list中的對象過多時,會觸發GC,如果GC后仍然不足,則OOMif (list.size() > 500) { // 移除一部分對象,使其變為可回收狀態for (int i = 0; i < 200; i++) {list.remove(0);}System.out.println("移除200個對象,當前對象數量: " + list.size());}}} catch (OutOfMemoryError e) {System.err.println("發生OutOfMemoryError: " + e.getMessage());System.out.println("程序退出。");}}
}

代碼說明:

  • 我們創建了一個ArrayList來持有byte[]對象,每個byte[]的大小為1MB。
  • while(true)循環中,我們不斷創建新的byte[]對象并添加到list中。
  • count % 100 == 0用于每創建100MB對象時打印一條消息,并暫停100毫秒,模擬實際應用中的業務處理。
  • list中的對象數量超過500個時,我們手動移除前200個對象。這些被移除的對象將不再被list引用,從而有機會被垃圾回收器回收。
  • 當JVM內存不足以分配新的byte[]對象時,會觸發垃圾回收。如果垃圾回收后仍然無法獲得足夠的內存,就會拋出OutOfMemoryError

如何運行和觀察:

  1. 將上述代碼保存為GcExample.java
  2. 使用javac GcExample.java編譯。
  3. 使用java -Xmx256m -Xms256m GcExample運行。其中-Xmx256m-Xms256m分別設置JVM的最大堆內存和初始堆內存為256MB。您可以根據需要調整這些參數來觀察不同的GC行為。

在運行過程中,您會觀察到程序不斷創建對象,當內存接近上限時,JVM會進行垃圾回收,控制臺可能會打印GC相關信息(如果開啟了GC日志)。當內存實在不足時,就會拋出OutOfMemoryError

總結與展望

本文深入探討了Java虛擬機(JVM)的架構、內存管理、垃圾回收機制以及性能優化策略。我們了解到,JVM作為Java程序的運行基石,其內部機制的復雜性與精妙性并存。從類加載器加載字節碼,到運行時數據區管理內存,再到執行引擎執行字節碼,每一個環節都緊密協作,共同構成了Java程序高效、穩定運行的基礎。

特別是JVM的自動內存管理機制,通過垃圾回收器極大地簡化了開發者的內存管理負擔,但也要求我們理解其工作原理,以便在出現內存問題時能夠快速定位和解決。各種垃圾回收算法和收集器的演進,也體現了JVM在不斷追求更短停頓時間、更高吞吐量和更好用戶體驗的努力。

性能優化是Java應用開發中永恒的話題。通過合理的JVM參數調優、對常見性能問題的排查以及利用專業的監控工具,我們可以顯著提升Java應用的性能和穩定性。然而,JVM的優化并非一蹴而就,它需要開發者在實踐中不斷積累經驗,結合具體的應用場景進行分析和調整。

隨著云計算、微服務和大數據技術的飛速發展,Java和JVM依然是構建高性能、高并發應用的首選技術棧之一。未來,JVM將繼續在內存管理、垃圾回收、即時編譯等方面進行創新,以適應不斷變化的計算環境和應用需求。深入學習和掌握JVM,將使我們能夠更好地駕馭Java這門強大的語言,構建出更加卓越的軟件系統。

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

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

相關文章

PHP SimpleXML:深入理解與高效使用

PHP SimpleXML:深入理解與高效使用 引言 PHP SimpleXML 是一個用于解析和操作 XML 文檔的庫。它簡化了 XML 的處理過程,使得 PHP 開發者可以更加輕松地與 XML 數據交互。本文將深入探討 PHP SimpleXML 的基本概念、使用方法以及在實際開發中的應用。 SimpleXML 簡介 Simp…

雙模秒切,體驗躍遷!飛利浦EVNIA雙模游戲顯示器27M2N6801M王者降臨!

當沉浸式畫質與電競級流暢無法共存&#xff0c;EVNIA Mini LED雙模游戲顯示器27M2N6801M以破界之姿革新而來&#xff01;全新搭載 4K160Hz / FHD320Hz雙模顯示引擎&#xff0c;將視覺震撼與操作跟手性推向全新高度。心念所動間&#xff0c;即可在電影級3A世界與分秒必爭的電競戰…

Transformer:自注意力驅動的神經網絡革命引擎

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; 從語言理解到多模態智能的通用架構基石 ?? 一、核心定義與歷史意義 …

汽車電子電氣架構中的關鍵計算單元解析

汽車電子電氣架構正經歷從分布式到集中式的重大變革&#xff0c;ECU、域控制器、中央計算單元等計算設備在這一演進過程中扮演著不同角色。這些設備按功能層級可分為傳統控制層、域集中層和中央計算層&#xff0c;各自承擔特定計算任務&#xff0c;共同構成智能汽車的"大腦…

Pandas 學習(數學建模篇)

今天學習數學建模2023年C篇&#xff08;228&#xff09;優秀論文 2023高教社杯全國大學生數學建模競賽C題論文展示&#xff08;C228&#xff09; - 2023C題論文 - 中國大學生在線 一.pd.DataFrame pd.DataFrame() 是 pandas 庫中用于創建二維表格數據結構&#xff08;DataFr…

第七講:C++中的string類

目錄 1、認識string類 2、標準庫中的string類 2.1、string類的常見接口 2.1.1、構造與賦值重載 2.1.2、迭代器 2.1.3、容量 2.1.4、訪問 2.1.5、修改 2.1.6、字符串操作 2.1.7、成員常量 2.1.8、非成員函數 2.1.9、轉換函數 2.2、vs和g下的string 2.2.1、vs下的s…

elementUI 前端表格table數據導出(一)

為啥前端導出不在贅述了第一步&#xff1a;安裝xlsxnpm install xlsx第二步&#xff1a;創建js文件html2excelimport * as XLSX from xlsx;const htmlToExcel {getExcel(dom, title temp){var excelTitle title;// const XLSX require("xlsx");var wb XLSX.util…

LabVIEW 波形圖表橫坐標顯示當前日期

LabVIEW 程序如何實現波形圖表橫坐標顯示當前日期一、XY Graph 時間關聯邏輯&#xff08;右上角分支&#xff09;功能本質實時采集當前系統時間&#xff08;秒數形式&#xff0c;基于 1904 基準&#xff09;&#xff0c;直接映射為 XY Graph 的 X 軸時間標識&#xff0c;實現動…

Android Soundtrigger喚醒相關時序學習梳理

本文所寫內容是在高通芯片平臺相關代碼基礎上學習整理匯總&#xff0c;如有描述不當之處&#xff0c;歡迎指正&#xff01;1、SoundTrigger注冊喚醒監聽事件回調流程&#xff08;SoundTrigger HAL層到ADSP層&#xff0c;不包括FWK層&#xff09;//(1)SoundTriggerSession 回調 …

OSPF實驗以及核心原理全解

OSPF&#xff08;Open Shortest Path First&#xff0c;開放式最短路徑優先&#xff09;是一種基于鏈路狀態的內部網關協議&#xff08;IGP&#xff09;&#xff0c;廣泛應用于中大型網絡中。它通過維護網絡拓撲信息&#xff0c;使用 SPF&#xff08;最短路徑優先&#xff09;算…

Using Spring for Apache Pulsar:Transactions

本節介紹Spring for Apache Pulsar如何支持事務。OverviewSpring for Apache Pulsar事務支持是基于Spring Framework提供的事務支持構建的。在高層&#xff0c;事務資源向事務管理器注冊&#xff0c;事務管理器反過來處理注冊資源的事務狀態&#xff08;提交、回滾等&#xff0…

在Ubuntu上從零開始編譯并運行Home Assistant源碼并集成HACS與小米開源的Ha Xiaomi Home

目錄1. 前言&&疊甲2. 使用的環境3. 相關鏈接4. 前期步驟4.1 安裝路徑提前說明4.2 Ubuntu 相關依賴安裝4.3 Python源碼編譯安裝4.3.1 編譯安裝4.3.2 換源4.3.3 環境變量5. 構建Home Assistant源碼5.1 clone源碼5.2 創建虛擬Python環境5.3 安裝項目依賴5.4 安裝項目5.5 運…

【實習篇】之Http頭部字段之Disposition介紹

Http頭部字段之DispositionDisposition頭部字段介紹RFC規范介紹RFC 6266與RFC 2047實習的時候公司將一個某個關于下載的Bug交給了我來修&#xff0c;看了代碼和日志后發現是Disposition字段的規范兼容性惹的鍋&#xff0c;因為有些協議使用的是老協議&#xff0c;我們的項目沒有…

VM文件管理與Vi/vim操作

[rootlocalhost /]# sudo mkdir /opt [rootlocalhost /]# sudo mkdir /opt/tmp [rootlocalhost /]# sudo touch /opt/tmp/a.txt [rootlocalhost /]# ls /opt/tmp/ a.txt [rootlocalhost /]# 3.步驟1&#xff1a;創建文件并插入日期時間vi /tmp/newfile在vi編輯器中輸入以下命令…

【Android】安卓四大組件之內容提供者(ContentProvider):從基礎到進階

你手機里的通訊錄&#xff0c;存儲了所有聯系人的信息。如果你想把這些聯系人信息分享給其他App&#xff0c;就可以通過ContentProvider來實現。。 一、什么是 ContentProvider ?ContentProvider? 是 Android 四大組件之一&#xff0c;負責實現?跨應用程序的數據共享與訪問…

Vue-19-前端框架Vue之應用基礎組件通信(二)

文章目錄 1 v-model(父子相傳)1.1 App.vue1.2 Father.vue1.2.1 v-model用在html標簽上1.2.2 v-model用在html標簽上(本質寫法)1.2.3 v-model用在組件標簽上1.2.4 v-model用在組件標簽上(本質寫法)1.3 MyInput(自定義的組件)1.4 修改modelValue1.4.1 Father.vue1.4.2 MyInput.vu…

寶塔下載pgsql適配spring ai

1.寶塔安裝pgvector 1.先去github下載pgvectorpgvector/pgvector: Open-source vector similarity search for Postgres 2.把壓縮包上傳到系統文件的/temp下解壓&#xff0c;重命名文件名為pgvector&#xff0c;之后命令操作 cd /tmp cd pgvector export PG_CONFIG/www/serv…

RK3568項目(八)--linux驅動開發之基礎外設(上)

目錄 一、引言 二、準備工作 ------>2.1、驅動加載/卸載命令 三、字符設備驅動開發 ------>3.1、驅動模塊的加載和卸載 ------>3.2、外部模塊編譯模板 Makefile ------>3.3、cdev 四、LED驅動 ------>4.1、原理圖 ------>4.2、驅動 五、設備樹 -…

BUUCTF在線評測-練習場-WebCTF習題[GXYCTF2019]BabySQli1-flag獲取、解析

解題思路打開靶場&#xff0c;題目提示是sql注入輸入數據&#xff0c;判斷下閉合11123報錯&#xff1a;Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 1 at line 1報錯提示…

“AI 曼哈頓計劃”:科技競賽還是人類挑戰?

美國國會下屬的經濟與安全審查委員會已將“推動建立并資助一項堪比曼哈頓計劃的通用人工智能研發項目”列為其對國會的核心建議之一&#xff0c;明確顯示出對AI競賽戰略意義的高度重視。與此同時&#xff0c;美國能源部在近幾個月中多次公開將人工智能的突破比作“下一場曼哈頓…