JVM原理-基礎篇

Java虛擬機(JVM, Java Virtual Machine)是運行Java應用程序的核心組件,它是一個抽象化的計算機系統模型,為Java字節碼提供運行環境。JVM的主要功能包括:類加載機制、內存管理、垃圾回收、指令解釋與執行、異常處理與安全檢查、性能優化等。

目錄

一、初識JVM

1.1、JVM基礎知識

1.2、JVM的組成部分

二、字節碼文件詳解

2.1、字節碼文件的基本組成

2.2、類加載器

三、JVM的內存區域

四、JVM的垃圾回收機制

4.1、自動垃圾回收

4.2、方法區的回收

4.3、堆內存的回收


一、初識JVM

1.1、JVM基礎知識

1.什么是JVM?

JVM是java虛擬機,本質上是運行在計算機上的程序,它的職責是運行Java字節碼文件。

正常我們編寫的是.java文件,通過javac進行編譯成.class的字節碼文件,然后由JVM進行加載并解釋成為機器碼。

2.JVM的三大功能?

JVM的第一個作用是類加載并對對字節碼文件的指令進行解釋成機器碼。

JVM的第二個功能是內存管理,主要包括為對象分配內存,以及垃圾回收等。

JVM的第三個功能是即時編譯,對熱點代碼進行優化,提升執行效率。

java語言是先編譯成字節碼文件,再通過jvm解釋成可執行的機器碼文件。C/C++是直接編譯鏈接成可執行的.exe文件,所以一般來說C/C++語言的性能更高。

Java語言的實時解釋主要是為了實現跨平臺特性,相當于一次編譯成字節碼文件,可以不同的平臺通過JVM進行解釋運行。

3.常見的JVM有哪些?

常見的虛擬機有如下幾種,其中HotSpot是JDK默認自帶的虛擬機。

1.2、JVM的組成部分

JVM主要包括如下幾部分:類加載器、運行時數據區、執行引擎、本地接口四個部分。

1.類加載器:加載class字節碼文件中的內容到內存中。

2.運行時數據區:負責管理JVM所使用的內存,比如創建對象和銷毀對象。

3.執行引擎:將字節碼中的文件解釋成機器碼,同時使用即時編譯器優化性能。

4.本地接口:調用本地已經編譯的方法,比如虛擬機中提供的c/c++方法。

其中運行時數據區包括大部分:

  • 堆:存儲對象實例和數組,是所有線程共享的一塊區域,也是垃圾回收的主要區域。
  • 虛擬機棧:每個線程都有自己的棧空間,用于存放基本類型的變量、對象引用以及方法調用的上下文信息(如局部變量表、操作數棧等)。
  • 方法區:存儲類元數據(如類的結構信息)、靜態變量、常量池和即時編譯后的代碼等。
  • 程序計數器:記錄當前線程執行字節碼的位置。
  • 本地方法棧:為JNI調用的本地方法服務。

二、字節碼文件詳解

2.1、字節碼文件的基本組成

注意:直接使用記事本打開字節碼文件會是亂碼,一般來說使用jclasslib工具可以查看字節碼文件

字節碼文件主要包含如下5個部分:

1.基礎信息:魔數、字節碼對應的Java版本號、訪問標識、父類與接口。

2.常量池:保存了字符串常量、類或者接口名主要在字節碼指令中使用。

3.字段:當前類或者接口聲明的字段信息。

4.方法:當前類或者接口聲明的方法信息。

5.屬性:類的屬性,比如源碼的文件名、內部類的列表等。

2.2、類加載器

1.類的生命周期?

加載->連接(驗證、準備、解析)->初始化->使用->卸載

加載:類加載器根據類的全限名通過不同的渠道以二進制流的方式獲取字節碼信息。類加載完成后JVM會把字節碼信息放到方法區中。Java虛擬機還會在堆中生成一份與方法區中類似的java.lang.Class。

連接:驗證階段是驗證內容是否滿足java虛擬機規范,準備階段是靜態變量賦初值,解析階段是將常量池中的符號引用替換成指向內存的直接引用。

驗證:

1.對文件 格式的校驗以及主次版本號是否滿足當前Java虛擬機版本要求。例如:主版本號不允許超過運行環境的版本號,如果主版本號相等,副版本號也不能超過。

2.元信息驗證,比如類必須有父類。

3.驗證程序執行指令的語義。

4.符號引用驗證,例如是否訪問了其他類中private修飾的方法。

準備:

final修飾的基本數據類型的靜態變量,準備階段會對變量賦終值。

解析:

將常量池中的符號引用替換為直接引用。

符號引用:在字節碼文件中使用編號來訪問常量池中的內容。

直接引用:不再使用編號,使用內存中的地址進行具體數據的訪問。

初始化:

初始化階段會執行靜態代碼塊中的代碼,并為靜態變量賦初值。本質上就是初始化階段會執行字節碼文件中cliniit部分的指令。

以下幾種方式會導致類的初始化:

1.訪問一個類的靜態變量或者靜態方法,注意final修飾的常量不會觸發初始化 。

2.調用Class.forName()

3.new一個該類的對象時

4.執行Main方法中的當前類

2.常見的類加載器有哪些?

類加載器是Java虛擬機提供給應用程序去實現獲取類或接口的字節碼數據的技術。

啟動類加載器(BootStrap ClassLoader):用于加載一些核心類,由HotSpot虛擬機提供,使用 C++編寫的類加載器。

擴展類加載器器:用于加載一些擴展類,由JDK提供,使用Java編寫的類加載器。

應用程序類加載器:用于加載應用第三方jar包里的類,由JDK提供,使用Java編寫的類加載器。

3.雙親委派機制的作用,什么是雙親委派機制?

作用:通過雙親委派機制避免惡意代碼替換JDK中的核心類庫,確保核心類庫的完整性和安全性,另外可以避免同一個類被多次加載。

雙親委派機制:類加載器在加載之前會向上查找其父類是否加載過,如果父類加載過則直接返回,父類能未加載過則判斷能否加載(是否在類加載器的加載目錄路徑中),能加載就加載,不能加載則由子類加載。

4.如何打破雙親委派機制?為什么要打破雙親委派機制?

打破雙親委派機制的三種方式:
1.自定義類加載器并重寫LoadClass方法,就可以把雙親委派機制的代碼清除

2.利用上下文類加載器加載類,例如:JDBC和 JNDI等

3.利用Osgi框架的類加載器

  • 實現特殊的需求:在某些情況下,可能需要加載特殊的類或者自定義類加載邏輯,例如實現熱替換(HotSwapping)功能,或者實現隔離的類加載環境,如OSGi、Tomcat容器等,這些場景下需要自定義類加載器并改變類加載的順序和規則。
  • 實現版本隔離或多重類加載:在某些框架或應用服務器中,為了支持多個版本的同一類庫共存,或者為了實現模塊化加載,需要打破雙親委派,讓每個模塊擁有獨立的類加載器來加載自己的類。

三、JVM的內存區域

內存溢出(OOM):程序在使用某一塊內存區域時,存放的數據占用內存大小超出了虛擬機所能提供的最大內存上限。

1.Java的內存區域?

程序計數器(線程不共享):每個線程通過程序計數器記錄當前要執行的字節碼指令的地址。在程序執行過程中,程序計數器會記錄下一行字節碼指令的地址,執行完當前指令后,java虛擬機的執行引擎會根據指令計數器執行下一行 指令。具體來說程序計數器有兩個作用:1.記錄指令執行的地址并控制線程執行指令。2.多線程執行指令,線程切換時候用來記錄線程執行到指令的地址。

程序計數器不會產生內存溢出,因為每個線程只是存儲一個固定長度的內存地址。

Java虛擬機棧(線程不共享):Java虛擬機棧隨著線程的創建而創建,隨著線程的銷毀而回收。java虛擬機棧存放的是棧幀,棧幀包含三部分:局部變量表、操作數棧、幀數據。

局部變量表:程序在運行過程中,存放執行方法的所有局部變量。局部變量表本質上是一個數組,數組中每個位置稱為一個槽,long和double占2個槽,其它類型占1個槽。局部變量保存的內容:實例方法的this,方法的參數,方法體中聲明的局部變量。為了節省空間,局部變量表的槽是可以復用的,一旦某個局部變量失效,當前的槽就可以被復用。

操作數棧:是虛擬機在執行指令的過程用來存放臨時數據的一塊區域。比如:當前指令的值壓入操作數棧中,后面的指令可以彈出并使用該值。在編譯時期就可以確定操作數棧的最大深度,從而在執行的時候正確分配內存大小。

幀數據:動態鏈接、方法出口、異常表的引用。動態鏈接用于保存符號引用到運行時常量池內存地址的一個映射關系。方法出口存放的是棧幀中下一個指令的執行地址。異常表存放的是代碼中異常的處理信息,包括異常捕獲的生效范圍以及發生異常后跳轉到字節碼指令的位置。

要修改 Java虛擬機棧的大小,可以使用虛擬機參數-Xss,例如:-Xss256k

虛擬機HotSpot對棧的最大值與最小值有要求,例如:windows下jdk8的運行虛擬機棧的范圍在180k-1024m之間。另外,局部變量過多或者操作數棧深度過大也可能影響棧內存的大小。

本地方法棧(線程不共享):和Java虛擬機棧類似,用于服務native方法。Java虛擬機棧存儲的是Java方法調用時的棧幀,而本地方法棧存儲的是native本地方法的棧幀。在HotSpot虛擬機中,Java虛擬機棧和本地方法棧使用同一塊內存空間。

(線程共享):創建出來的對象存在堆內存中,堆內存的大小是有上限的,當一直向堆中放入對象達到上限之后就會拋出OutOfMemory(OOM)的錯誤。要修改虛擬機堆的大小可以使用參數:

-Xmx值(max最大值)? -Xms值(初始的total) 建議將這兩個值設置為相同大小的,這樣程序在啟動的時候使用的總的內存就是最大的內存,無需向Java虛擬機再次申請,減少堆內存申請的開銷。

方法區(線程共享):主要存放三部分的信息:1.類的基本信息,2.運行時常量池:字節碼文件的常量池內容,3.字符串常量池內容。在類加載階段,方法區會存放類的基本信息。JDK7及之前的版本將方法區放在堆內存中的永久代中,堆的大小由虛擬機控制;JDK8及之后的版本將方法區放到了元空間中,元空間位于操作系統維護的直接內存中,默認只要不超過操作系統承受的上限,則可以一直分配。運行時常量池主要用于存儲編譯期生成的各種字面量和符號引用。字符串常量池主要用于存儲字符串字面量的對象引用地址的一個區域。

注意:String類型的字符串,如果是變量拼接,則轉換成StringBuilder,如果是常量拼接,則直接拼接。

直接內存:JDK8及其以后方法區就存在直接內存的元空間中。

四、JVM的垃圾回收機制

4.1、自動垃圾回收

內存泄漏:指的是不再使用的對象在系統中未被回收,內存泄漏的累積可能會導致內存溢出。

在C/C++這類語言中沒有自動垃圾回收機制,一個對象不再使用,需要手動釋放,否則會導致內存泄漏 。

Java為了簡化對象的釋放,引入了自動垃圾回收機制,通過垃圾回收器來對不再使用的對象進行回收,垃圾回收器主要是對堆上的內存進行回收。

4.2、方法區的回收

我們知道類的聲明周期包括:加載,連接(驗證,準備,解析),初始化,使用,卸載五個部分,其中最后一步的卸載就是方法區的回收。

判斷一個類是否可以被卸載需要同時滿足以下三個條件:

1.此類的所有實例對象都已經被回收,在堆中不存在該類的任何實例對象以及子類對象。

2.加載該類的類加載器已經被回收。

3.該類對應的java.lang.Class對象在任何地方都沒有被引用。

如果需要手動回收垃圾,需要使用 System.gc()方法

4.3、堆內存的回收

1.常見的垃圾回收算法?

引用計數法與可達性分析法

引用計數法:為每個對象維護一個引用計數器,當對象被應用則加1,取消引用則減1。該方法優點是十分簡單。缺點:存在循環引用的問題,A引用B且B也引用A,假如應用程序不再需要這兩個對象,但是 引用 計數器不為0,所以導致這兩個對象無法回收,會出現內存泄漏。


可達性分析法:Java使用的是可達性分析算法來判斷對象是否可以回收,可達性分析將對象分為兩類:垃圾回收的根對象(GC Root)與普通對象,對象與對象之間存在引用關系。如果從普通對象到根對象的引用鏈是不可達的,則說明該對象則是可回收的。

那么哪些對象可以被稱為是GCRoot對象呢,以下四類可以被稱為垃圾回收根對象:
1)線程Thread對象

2)系統類加載器加載的 java.lang.Class對象

3)監視器對象,用來保存同步鎖synchronized關鍵字持有的對象

4)本地方法調用時使用的全局對象

標記清除法:在可達性分析算法確定了哪些對象是可達(存活)之后,垃圾收集器將對那些不可達的對象進行標記操作。標記完成后,垃圾收集器會清除所有被標記為不可達的對象占用的內存空間。優點:實現簡單,第一階段進行標記,第二階段進行清除即可。缺點:內存碎片化,清除掉一些碎片的內存可能導致無法再分配空間,維護鏈表進行分配,分配速度慢。

標記復制法:當前存活的對象復制到另一塊空間,將當前的空間進行清理掉。優點:吞吐量高,復制后不會發生碎片化。缺點:內存空間的使用率低?。

標記壓縮法:也稱為標記整理算法,使用可達性分析標記存活的對象,將存活的對象移動到內存的一側,清理掉存活對象之前的內存空間。優點:內存使用率高,不會產生碎片化。缺點:整理算法的效率不高。

分代GC算法:分代垃圾回收將整個內存區域劃分成年輕代與老年代。

年輕代:該區域包含三個部分:伊甸園區Eden,幸存者區S0,幸存者區S1。

創建出來的對象首先會放入伊甸園區,如果Eden區滿了,就會觸發young GC,如果可以被回收,則回收,否則放入幸存者區,如果年輕代的對象一直沒回收,存活時間比較長的對象會被放入到老年代。當老年代不足的時候,且年輕代也滿了,無法放入新的對象就會觸發 full GC。

2.常見的垃圾回收器?

為什么分代GC算法要把堆內存空間 劃分成年輕代與老年代?

因為年輕代用于存放可以很快被回收的對象,比如:用戶訂單數據。老年代則存放長期存活的對象,比如 Spring的大部分Bean對象。在虛擬機的默認設置中,新生代的大小 要遠小于老年代的大小。總的來說,分代GC算法將堆分成新生代和老年代的主要原因可以分為如下三點:

1.可以通過調整年輕代和老年代的比例來適應不同類型的應用程序,提高內存的利用率和性能。

2.新生代和老年代選擇不同的垃圾回收算法,新生代一般選擇標記復制法,老年代一般選擇標記清除法與標記壓縮法,由程序員來選擇,靈活度較高。

3.分代的設計只允許回收新生代,如果能滿足對象分配的要求就不需要對整個堆進行回收,即不需要full GC。

常見的垃圾回收器:Serial、ParNew、Parallel Scavenge、CMS、Serial Old、Parallel Old

Serial是一種單線程串行的年輕代垃圾回收器,使用的是標記復制法,適用于單cpu進行處理垃圾回收,不適用于多cpu下的處理,多cpu下可能會使得其它用戶線程處于長時間的等待狀態。

SerialOld是Serial的老年代版本,采用單線程串行回收,可以與Serial垃圾回收器搭配使用。

ParNew是年輕代的垃圾回收器,本質上是堆Serial進行多cpu下的優化,使用多線程進行垃圾回收,與老年代垃圾回收器CMS進行搭配使用。

CMS垃圾回收器關注的是系統的暫停時間,允許用戶線程和垃圾回收線程在某些步驟中同時進行,減少了用戶線程的等待時間。采用標記清除法,垃圾回收停頓的時間短,用戶體驗好,但是存在內存碎片化如果老年代內存不足會退化成單線程SerialOld回收。CMS適用于請求數據量大,頻率高的場景,例如:訂單接口、商品接口等。

Parallel Scavenge垃圾回收器:是JDK8默認的年輕代垃圾回收器,多線程并行回收,關注的是系統吞吐量,具備自動調節堆內存大小的特點。吞吐量高,但是不能保證單次的停頓時間,適用于后臺任務,比如:大數據的處理、大文件的導出等。

Parallel Old垃圾回收器:是為Parallel Scavenge設計的老年代的垃圾回收器,利用多線程并發收集,一般來說,使用Parallel Old+Parallel Scavenge組合,不需要設置堆內存的最大值,垃圾回收器會根據最大暫停時間和吞吐量自動調整堆內存的大小。

當發生STW時,JVM會暫停所有非垃圾收集線程(即除GC線程之外的所有用戶線程),STW事件會導致應用程序暫時失去響應,對于實時性要求高的應用來說,STW時間過長可能會對系統性能造成顯著影響。

G1垃圾回收器:是年輕代和老年代的垃圾回收器,JDK9開始之后默認的垃圾回收器,G1垃圾回收器是結合了CMS垃圾回收器與Parallel Scavenge垃圾回收器的優點,具備以下三個優點:1.支持大的堆空間的回收,并有較高的吞吐量。2.支持多CPU并行垃圾回收。3.允許用戶設置最大暫停時間。

G1的整個堆會被劃分成多個大小相等的區域,區域不要求連續,具體分為:伊甸園區、幸存者區、老年代區。G1的垃圾回收有兩種方式:年輕代回收(young GC),回收伊甸園區和幸存者區不用的對象,年輕代不足,會觸發young GC,使用標記復制法進行垃圾清理。

當某個對象被復制多次,存活年齡達到閾值15,該對象將會被移入老年代,多次回收后,會出現很多的老年代區,此時總堆的占有率達到閾值,此時會采用標記復制法回收年輕代與老年代的對象。G1老年代的清理會選擇存活度最低的區域進行回收,可以保證回收效率最高。如果發現沒有足夠的區域存放轉移的對象,會觸發full GC,單線程執行標記整理算法,會導致用戶線程的暫停。

3.Java中四種引用方式?
強引用:通過可達性分析判斷,對象被引用則不是垃圾,若對象到GCRoot不可達,可以認為是垃圾,會被回收掉。當內存不足的時候,只有對象被引用,就不會被回收。

軟引用:當程序內存不足的時候,軟引用對象會被回收掉。SoftReference類來實現軟引用。軟引用對象回收后,內存仍然不足可能會報OOM。

弱引用:使用弱引用的對象,再使用完成后無論是否存在引用都會被回收掉。弱引用使用WeakReference類來實現,弱引用主要在ThreadLocal中使用。

虛引用:虛引用的作用是對象被垃圾回收器回收的時候可以收到相應的通知。

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

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

相關文章

React react.fragment和<>的使用及區別

React一個常用的模式是組件返回多個元素。Fragment可以為你的子元素分組而不需要在DOM上為它們添加額外的節點。 Fragment 使用 render() {return (<React.Fragment> <ChildA /> <ChildB /> <ChildC /> </React.Fragment> );}短語法使用 這里…

虛擬機內存不夠用了?全流程操作Look一下?

虛擬機信息&#xff1a;操作系統&#xff1a;CentOS Linux 7 (Core)&#xff0c;用的是VMware Workstation 16 Pro 版本16.2.3 build-19376536&#xff1b;我的主機 Windows 10 Education, 64-bit (Build 22000.1817) 10.0.22000 前言&#xff1a;虛擬機用久了就會出現內存不足…

代碼隨想錄算法訓練營Day37|738.單調遞增的數字、968.監控二叉樹

738.單調遞增的數字 題目鏈接&#xff1a;738.單調遞增的數字 文檔鏈接&#xff1a;738.單調遞增的數字 視頻鏈接&#xff1a;貪心算法&#xff0c;思路不難想&#xff0c;但代碼不好寫&#xff01;LeetCode:738.單調自增的數字 C實現 class Solution { public:int monotoneIn…

Rocky Linux 安裝部署 Zabbix 6.4

一、Zabbix的簡介 Zabbix是一種開源的企業級監控解決方案&#xff0c;用于實時監測服務器、網絡設備和應用程序的性能和可用性。它提供了強大的數據收集、處理和可視化功能&#xff0c;同時支持事件觸發、報警通知和自動化任務等功能。Zabbix易于安裝和配置&#xff0c;支持跨平…

6、Redis-KV設計、全局命令和安全性

目錄 一、value設計 二、Key設計 三、全局命令——針對所有key 四、安全性 一、value設計 ①是否需要排序&#xff1f;需要&#xff1a;Zset ②需要緩存的數據是單個值還是多個值&#xff1f; 單個值&#xff1a;簡單值---String&#xff1b;對象值---Hash多個值&#x…

【前端素材】推薦優質后臺管理系統網頁Hyper平臺模板(附源碼)

一、需求分析 1、系統定義 后臺管理系統是一種用于管理和控制網站、應用程序或系統的管理界面。它通常被設計用來讓網站或應用程序的管理員或運營人員管理內容、用戶、數據以及其他相關功能。后臺管理系統是一種用于管理網站、應用程序或系統的工具&#xff0c;通常由管理員使…

【AIGC】OpenAI推出王炸級模型sora,顛覆AI視頻行業(2024)

對于OpenAI推出的Sora模型&#xff0c;我們可以進一步探討其可能的技術細節、潛在應用以及對AI視頻行業的影響。 點擊以下任一云產品鏈接&#xff0c;跳轉后登錄&#xff0c;自動享有所有云產品優惠權益&#xff1a; 經過筆者親測&#xff0c;強烈推薦騰訊云輕量應用服務器作…

【分類討論】【割點】1568. 使陸地分離的最少天數

作者推薦 動態規劃的時間復雜度優化 本文涉及知識點 分類討論 割點 LeetCode1568. 使陸地分離的最少天數 給你一個大小為 m x n &#xff0c;由若干 0 和 1 組成的二維網格 grid &#xff0c;其中 1 表示陸地&#xff0c; 0 表示水。島嶼 由水平方向或豎直方向上相鄰的 1 …

接口詳細說明

接口概述 接口也是一種規范 接口的定義與特點 接口的格式如下&#xff1a; //接口用關鍵字interface來定義 public interface 接口名 {// 常量// 抽象方法 } JDK8之前接口中只能是抽象方法和常量&#xff0c;沒有其他成分了。 接口不能實例化。 接口中的成員都是public修…

webpack打包一個文件,做了哪些事情

用webpack打包一個文件&#xff0c;在webpack內部做了哪些事情&#xff0c;用代碼詳細介紹一下 當你使用 Webpack 打包一個文件時&#xff0c;Webpack 內部會進行一系列操作來實現模塊加載、代碼轉換、依賴分析、模塊打包等功能。以下是使用 Webpack 打包一個簡單 JavaScript …

svn介紹 4.0

一、svn介紹&#xff08;版本控制工具&#xff09; 1、svn的定義&#xff1a; svn是一個開放源代碼的版本控制系統&#xff0c;通過采用分支管理系統的高效管理&#xff0c;簡而言之就是用于多個人共同開發同一個項目&#xff0c;實現共享資源&#xff0c;實現最終集中式個管…

電腦數據丟失是什么原因 易我數據恢復軟件下載 easyrecovery數據恢復軟件下載 電腦數據刪除了怎么恢復 電腦數據庫損壞了怎么找回

目錄 一、電腦數據丟失是什么原因 二、電腦數據丟失如何恢復 三、EasyRecovery恢復電腦數據的方法介紹 電腦是我們大家熟悉并且常用的數據存儲設備&#xff0c;也是綜合性非常強的數據處理設備。對于電腦設備來講&#xff0c;最主要的數據存儲介質是硬盤&#xff0c;電腦硬…

CMU15445實驗總結(Spring 2023)

CMU15445實驗總結(Spring 2023) 背景 菜鳥博主是2024屆畢業生&#xff0c;學歷背景太差&#xff0c;導致23年秋招無果&#xff0c;準備奮戰春招。此前有讀過LevelDB源碼的經歷&#xff0c;對數據庫的了解也僅限于LevelDB。奔著”有對比才能學的深“的理念&#xff0c;以及緩解…

linux系統Jenkins工具配置webhook自動部署

Jenkins工具webhook自動部署 webhook自動部署webhook的意義操作流程jenkins頁面操作gitlab頁面操作 webhook自動部署 webhook的意義 自動化部署&#xff1a;Webhook 可以在代碼提交、合并請求或其他特定事件發生時自動觸發 Jenkins 構建和部署任務&#xff0c;從而實現自動化…

C#,K中心問題(K-centers Problem)的算法與源代碼

1 K中心問題&#xff08;K-centers Problem&#xff09; k-centers problem: 尋找k個半徑越小越好的center以覆蓋所有的點。 比如&#xff1a;給定n個城市和每對城市之間的距離&#xff0c;選擇k個城市放置倉庫&#xff08;或ATM或云服務器&#xff09;&#xff0c;以使城市…

【JavaEE進階】 Spring AOP源碼簡單剖析

文章目錄 &#x1f343;前言&#x1f340;Spring AOP源碼剖析?總結 &#x1f343;前言 前面的博客中&#xff0c;博主對代理模式進行了一個簡單的講解&#xff0c;接下來博主將對Spring AOP源碼進行簡單剖析&#xff0c;使我們對Spring AOP了解的更加深刻。 &#x1f340;Sp…

leetcode 簡單

1. 兩數之和 兩數之和 方法1&#xff1a;暴力枚舉 兩次for 循環&#xff0c;記錄索引和值&#xff0c;找到合適的值然后返回 方法2&#xff1a;使用哈希表 第一次for循環的時候&#xff0c;就可以使用哈希表記錄key的value&#xff0c;可以實現時間復雜度是1&#xff0c;要分…

【前端素材】推薦優質后臺管理系統網頁Highdmin平臺模板(附源碼)

一、需求分析 1、系統定義 后臺管理系統是一種用于管理和控制網站、應用程序或系統的管理界面。它通常被設計用來讓網站或應用程序的管理員或運營人員管理內容、用戶、數據以及其他相關功能。后臺管理系統是一種用于管理網站、應用程序或系統的工具&#xff0c;通常由管理員使…

express+mysql+vue,從零搭建一個商城管理系統7--文件上傳,大文件分片上傳

提示&#xff1a;學習express&#xff0c;搭建管理系統 文章目錄 前言一、安裝multer&#xff0c;fs-extra二、新建config/upload.js三、新建routes/upload.js四、修改routes下的index.js五、修改index.js六、新建上傳文件test.html七、開啟jwt驗證token&#xff0c;通過login接…

Vue.js+SpringBoot開發開放實驗室管理系統

目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、研究內容2.1 實驗室類型模塊2.2 實驗室模塊2.3 實驗管理模塊2.4 實驗設備模塊2.5 實驗訂單模塊 三、系統設計3.1 用例設計3.2 數據庫設計 四、系統展示五、樣例代碼5.1 查詢實驗室設備5.2 實驗放號5.3 實驗預定 六、免責說明 一、摘…