主頁 > 後端開發 > 吐血整理收集時間長達一個月的Java: JVM(生命周期、結構體系、堆、堆疊、運行機制&原理)核心知識要點梳理

吐血整理收集時間長達一個月的Java: JVM(生命周期、結構體系、堆、堆疊、運行機制&原理)核心知識要點梳理

2020-12-03 09:41:55 後端開發

JVM的基礎概念

JVM的中文名稱叫Java虛擬機,它是由軟體技術模擬出計算機運行的一個虛擬的計算機,

JVM也充當著一個翻譯官的角色,我們撰寫出的Java程式,是不能夠被作業系統所直接識別的,這時候JVM的作用就體現出來了,它負責把我們的程式翻譯給系統“聽”,告訴它我們的程式需要做什么操作,

我們都知道Java的程式需要經過編譯后,產生.Class檔案,JVM才能識別并運行它,JVM針對每個作業系統開發其對應的解釋器,所以只要其作業系統有對應版本的JVM,那么這份Java編譯后的代碼就能夠運行起來,這就是Java能一次編譯,到處運行的原因,

在這里插入圖片描述
歡迎各位大佬進群共同交流學習,我們的交流分享群:1149778920 暗號:CSDN
博主在這里給大家整理了包括但不限于:JAVA基礎和進階類、Spring、Spring boot、Spring MVC、MyBatis、MySQL、JVM等各種資料有,免費分享給各位進群的小伙伴

在這里插入圖片描述

JVM的生命周期

JVM在Java程式開始執行的時候,它才運行,程式結束的時它就停止,

一個Java程式會開啟一個JVM行程,如果一臺機器上運行三個程式,那么就會有三個運行中的JVM行程,

JVM中的執行緒分為兩種:守護執行緒和普通執行緒

守護執行緒是JVM自己使用的執行緒,比如垃圾回收(GC)就是一個守護執行緒,

普通執行緒一般是Java程式的執行緒,只要JVM中有普通執行緒在執行,那么JVM就不會停止,

權限足夠的話,可以呼叫exit()方法終止程式,

JVM的結構體系

在這里插入圖片描述

JVM的啟動程序

1、JVM的裝入環境和配置

在學習這個之前,我們需要了解一件事情,就是JDK和JRE的區別,

JDK是面向開發人員使用的SDK,它提供了Java的開發環境和運行環境,JDK中包含了JRE,

JRE是Java的運行環境,是面向所有Java程式的使用者,包括開發者,

JRE = 運行環境 = JVM,

如果安裝了JDK,會發現電腦中有兩套JRE,一套位于/Java/jre…/下,一套位于/Java/jdk…/jre下,那么問題來了,一臺機器上有兩套以上JRE,誰來決定運行那一套呢?這個任務就落到java.exe身上,java.exe的任務就是找到合適的JRE來運行java程式,

java.exe按照以下的順序來選擇JRE:

  • 自己目錄下有沒有JRE

  • 父目錄下有沒有JRE

  • 查詢注冊表: HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"當前JRE版本號"\JavaHome

這幾步的主要核心是為了找到JVM的絕對路徑,

jvm.cfg的路徑為:JRE路徑\lib"CPU架構"\jvm.fig

jvm.cfg的內容大致如下:

  • client KNOWN
  • server KNOWN
  • hotspot ALIASED_TO -client
  • classic WARN
  • native ERROR
  • green ERROR

KNOWN 表示存在 、IGNORE 表示不存在 、ALIASED_TO 表示給別的JVM去一個別名
WARN 表示不存在時找一個替代 、ERROR 表示不存在拋出例外

2、裝載JVM

通過第一步找到JVM的路徑后,Java.exe通過LoadJavaVM來裝入JVM檔案,
LoadLibrary裝載JVM動態連接庫,然后把JVM中的到處函式JNI_CreateJavaVM和JNI_GetDefaultJavaVMIntArgs 掛接到InvocationFunction 變數的CreateJavaVM和GetDafaultJavaVMInitArgs 函式指標變數上,JVM的裝載作業完成,

3、初始化JVM,獲得本地呼叫介面

呼叫InvocationFunction -> CreateJavaVM也就是JVM中JNI_CreateJavaVM方法獲得JNIEnv結構的實體,

4、運行Java程式

JVM運行Java程式的方式有兩種:jar包 與 Class
運行jar 的時候,Java.exe呼叫GetMainClassName函式,該函式先獲得JNIEnv實體然后呼叫JarFileJNIEnv類中getManifest(),從其回傳的Manifest物件中取getAttrebutes(“Main-Class”)的值,即jar 包中檔案:META-INF/MANIFEST.MF指定的Main-Class的主類名作為運行的主類,之后main函式會呼叫Java.c中LoadClass方法裝載該主類(使用JNIEnv實體的FindClass),

運行Class的時候,main函式直接呼叫Java.c中的LoadClass方法裝載該類,

Class檔案

Class檔案由Java編譯器生成,我們創建的.Java檔案在經過編譯器后,會變成.Class的檔案,這樣才能被JVM所識別并運行,

類加載子系統

類加載子系統也可以稱之為類加載器,JVM默認提供三個類加載器:

  • BootStrap ClassLoader :稱之為啟動類加載器,是最頂層的類加載器,負責加載JDK中的核心類別庫,如 rt.jar、resources.jar、charsets.jar等,

  • Extension ClassLoader:稱之為擴展類加載器,負責加載Java的擴展類別庫,默認加載$JAVA_HOME中jre/lib/*.jar 或 -Djava.ext.dirs指定目錄下的jar包,

  • App ClassLoader:稱之為系統類加載器,負責加載應用程式classpath目錄下所有jar和class檔案,

除了Java默認提供的三個ClassLoader(加載器)之外,我們還可以根據自身需要自定義ClassLoader,自定義ClassLoader必須繼承java.lang.ClassLoader 類,除了BootStrap ClassLoader 之外的另外兩個默認加載器都是繼承自java.lang.ClassLoader ,BootStrap ClassLoader 不是一個普通的Java類,它底層由C++撰寫,已嵌入到了JVM的內核當中,當JVM啟動后,BootStrap ClassLoader 也隨之啟動,負責加載完核心類別庫后,并構造Extension ClassLoader 和App ClassLoader 類加載器,

類加載器子系統不僅僅負責定位并加載類檔案,它還嚴格按照以下步驟做了很多事情:

  • 加載:尋找并匯入Class檔案的二進制資訊

  • 連接:進行驗證、準備和決議

    1)驗證:確保匯入型別的正確性
    2)準備:為型別分配記憶體并初始化為默認值
    3)決議:將字符參考決議為直接參考

  • 初始化:呼叫Java代碼,初始化類變數為指定初始值

方法區(Method Area)

在JVM中,型別資訊和類靜態變數都保存在方法區中,型別資訊是由類加載器在類加載的程序中從類檔案中提取出來的資訊,

需要注意的一點是,常量池也存放于方法區中,

程式中所有的執行緒共享一個方法區,所以訪問方法區的資訊必須確保執行緒是安全的,如果有兩個執行緒同時去加載一個類,那么只能有一個執行緒被允許去加載這個類,另一個必須等待,

在程式運行時,方法區的大小是可以改變的,程式在運行時可以擴展,

方法區也可以被垃圾回收,但條件非常嚴苛,必須在該類沒有任何參考的情況下

型別資訊包括什么?

1、型別的全名(The fully qualified name of the type)

2、型別的父型別全名(除非沒有父型別,或者父型別是java.lang.Object)(The fully qualified name of the typeís direct superclass)

3、該型別是一個類還是介面(class or an interface)(Whether or not the type is a class )

4、型別的修飾符(public,private,protected,static,final,volatile,transient等)(The typeís modifiers)

5、所有父介面全名的串列(An ordered list of the fully qualified names of any direct superinterfaces)

6、型別的欄位資訊(Field information)

7、型別的方法資訊(Method information)

8、所有靜態類變數(非常量)資訊(All class (static) variables declared in the type, except constants)

9、一個指向類加載器的參考(A reference to class ClassLoader)

10、一個指向Class類的參考(A reference to class Class)

11、基本型別的常量池(The constant pool for the type)

方法串列(Method Tables)

為了更高效的訪問所有保存在方法區中的資料,在方法區中,除了保存上邊的這些型別資訊之外,還有一個為了加快存取速度而設計的資料結構:方法串列,每一個被加載的非抽象類,Java虛擬機都會為他們產生一個方法串列,這個串列中保存了這個類可能呼叫的所有實體方法的參考,保存那些父類中呼叫的方法,

Java堆(JVM堆、Heap)

當Java創建一個類的實體物件或者陣列時,都在堆中為新的物件分配記憶體,

虛擬機中只有一個堆,程式中所有的執行緒都共享它,

堆占用的記憶體空間是最多的,

堆的存取型別為管道型別,先進先出,

在程式運行中,可以動態的分配堆的記憶體大小,

Java堆疊(JVM堆疊、Stack)

在Java堆疊中只保存基礎資料型別(參考:Java 基本資料型別 - 四類八種 - 知乎專欄)和自定義物件的參考,注意只是物件的參考而不是物件本身哦,物件是保存在堆區中的,

拓展知識:像String、Integer、Byte、Short、Long、Character、Boolean這六個屬于包裝型別,它們是存放于堆中的,

堆疊的存取型別為類似于水杯,先進后出,

堆疊內的資料在超出其作用域后,會被自動釋放掉,它不由JVM GC管理,

每一個執行緒都包含一個堆疊區,每個堆疊中的資料都是私有的,其他堆疊不能訪問,

每個執行緒都會建立一個操作堆疊,每個堆疊又包含了若干個堆疊幀,每個堆疊幀對應著每個方法的每次呼叫,每個堆疊幀包含了三部分:

  • 區域變數區(方法內基本型別變數、變數物件指標)

  • 運算元堆疊區(存放方法執行程序中產生的中間結果)

  • 運行環境區(動態連接、正確的方法回傳相關資訊、例外捕捉)

本地方法堆疊

本地方法堆疊的功能和JVM堆疊非常類似,用于存盤本地方法的區域變數表,本地方法的運算元堆疊等資訊,

堆疊的存取型別為類似于水杯,先進后出,

堆疊內的資料在超出其作用域后,會被自動釋放掉,它不由JVM GC管理,

每一個執行緒都包含一個堆疊區,每個堆疊中的資料都是私有的,其他堆疊不能訪問,

本地方法堆疊是在程式呼叫或JVM呼叫本地方法介面(Native)時候啟用,

本地方法都不是使用Java語言撰寫的,比如使用C語言撰寫的本地方法,本地方法也不由JVM去運行,所以本地方法的運行不受JVM管理,

HotSpot VM將本地方法堆疊和JVM堆疊合并了,

程式計數器

在JVM的概念模型里,位元組碼解釋器作業時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、回圈、跳轉、例外處理、執行緒恢復等基礎功能都需要依賴這個計數器來完成,

JVM的多執行緒是通過執行緒輪流切換并分配處理器執行時間的方式來實作的,為了各條執行緒之間的切換后計數器能恢復到正確的執行位置,所以每條執行緒都會有一個獨立的程式計數器,

程式計數器僅占很小的一塊記憶體空間,

當執行緒正在執行一個Java方法,程式計數器記錄的是正在執行的JVM位元組碼指令的地址,如果正在執行的是一個Natvie(本地方法),那么這個計數器的值則為空(Underfined),

程式計數器這個記憶體區域是唯一一個在JVM規范中沒有規定任何OutOfMemoryError(記憶體不足錯誤)的區域,

JVM執行引擎

Java虛擬機相當于一臺虛擬的“物理機”,這兩種機器都有代碼執行能力,其區別主要是物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而JVM的執行引擎是自己實作的,因此程式員可以自行制定指令集和執行引擎的結構體系,因此能夠執行那些不被硬體直接支持的指令集格式,

在JVM規范中制定了虛擬機位元組碼執行引擎的概念模型,這個模型稱之為JVM執行引擎的統一外觀,JVM實作中,可能會有兩種的執行方式:解釋執行(通過解釋器執行)和編譯執行(通過即時編譯器產生本地代碼),有些虛擬機只采用一種執行方式,有些則可能同時采用兩種,甚至有可能包含幾個不同級別的編譯器執行引擎,

輸入的是位元組碼檔案、處理程序是等效位元組碼決議程序、輸出的是執行結果,在這三點上每個JVM執行引擎都是一致的,

本地方法介面(JNI)

JNI是Java Native Interface的縮寫,它提供了若干的API實作了Java和其他語言的通信(主要是C和C++),

JNI的適用場景

當我們有一些舊的庫,已經使用C語言撰寫好了,如果要移植到Java上來,非常浪費時間,而JNI可以支持Java程式與C語言撰寫的庫進行互動,這樣就不必要進行移植了,或者是與硬體、作業系統進行互動、提高程式的性能等,都可以使用JNI,需要注意的一點是需要保證本地代碼能作業在任何Java虛擬機環境,

JNI的副作用

一旦使用JNI,Java程式將丟失了Java平臺的兩個優點:

  • 程式不再跨平臺,要想跨平臺,必須在不同的系統環境下程式編譯配置本地語言部分,

  • 程式不再是絕對安全的,本地代碼的使用不當可能會導致整個程式崩潰,一個通用規則是,呼叫本地方法應該集中在少數的幾個類當中,這樣就降低了Java和其他語言之間的耦合,

JVM 常量池

JVM常量池也稱之為運行時常量池,它是方法區(Method Area)的一部分,用于存放編譯期間生成的各種字面量和符號參考,運行時常量池不要求一定只有在編譯器產生的才能進入,運行期間也可以將新的常量放入池中,這種特性被開發人員利用比較多的就是String.intern()方法,

由“用于存放編譯期間生成的各種字面量和符號參考”這句話可見,常量池中存盤的是物件的參考而不是物件的本身,

常量池的好處

常量池是為了避免頻繁的創建和銷毀物件而影響系統性能,它也實作了物件的共享,

例如字串常量池:在編譯階段就把所有字串文字放到一個常量池中,

  • 節省記憶體空間:常量池中如果有對應的字串,那么則回傳該物件的參考,從而不必再次創建一個新物件,

  • 節省運行時間:比較字串時,==比equals()快,對于兩個參考變數,==判斷參考是否相等,也就可以判斷實際值是否相等,

雙等號(==)的含義

基本資料型別之間使用雙等號,比較的是數值,

復合資料型別(類)之間使用雙等號,比較的是物件的參考地址是否相等,

八種基本型別的包裝類和常量池

Byte、Short、Integer、Long、Character、Boolean、String這7種包裝類都各自實作了自己的常量池,

//例子:
Integer i1 = 20;
Integer i2 = 20;
System.out.println(i1=i2);//輸出TRUE

Byte、Short、Integer、Long、Character這5種包裝類都默認創建了數值[-128 , 127]的快取資料,當對這5個型別的資料不在這個區間內的時候,將會去創建新的物件,并且不會將這些新的物件放入常量池中,

//IntegerCache.low = -128
//IntegerCache.high = 127
public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
//例子
Integer i1 = 200;
Integer i2 = 200;
System.out.println(i1==i2);//回傳FALSE

Float 和Double 沒有實作常量池,

String包裝類與常量池

String str1 = "aaa";

當以上代碼運行時,JVM會到字串常量池查找 “aaa” 這個字面量物件是否存在?

存在:則回傳該物件的參考給變數 str1 ,

不存在:則在堆中創建一個相應的物件,將創建的物件的參考存放到常量池中,同時將參考回傳給變數 str1 ,

String str1 = "aaa";
String str2 = "aaa";
System.out.println(str1 == str2);//回傳TRUE

因為變數str1 和str2 都指向同一個物件,所以回傳true,

String str3 = new String("aaa");
System.out.println(str1 == str3);//回傳FALSE

當我們使用了new來構造字串物件的時候,不管字串常量池中是否有相同內容的物件的參考,新的字串物件都會創建,因為兩個指向的是不同的物件,所以回傳FALSE ,

String.intern()方法

對于使用了new 創建的字串物件,如果想要將這個物件參考到字串常量池,可以使用intern() 方法,

呼叫intern() 方法后,檢查字串常量池中是否有這個物件的參考,并做如下操作:

存在:直接回傳物件參考給變數,

不存在:將這個物件參考加入到常量池,再回傳物件參考給變數,

String interns = str3.intern();
System.out.println(interns == str1);//回傳TRUE

假定常量池中都沒有以上字面量的物件,以下創建了多少個物件呢?

String str4 = "abc"+"efg";
String str5 = "abcefg";
System.out.println(str4 == str5);//回傳TRUE

答案是三個,第一個:“abc” ,第一個:“efg”,第三個:“abc”+“efg”(“abcefg”)

String str5 = “abcefg”; 這句代碼并沒有創建物件,它從常量池中找到了"abcefg" 的參考,所有str4 == str5 回傳TRUE,因為它們都指向一個相同的物件,

什么情況下會將字串物件參考自動加入字串常量池?

//只有在這兩種情況下會將物件參考自動加入到常量池
String str1 = "aaa";
String str2 = "aa"+"a";

//其他方式下都不會將物件參考自動加入到常量池,如下:
String str3 = new String("aaa");
String str4 = New StringBuilder("aa").append("a").toString();
StringBuilder sb = New StringBuilder();
sb.append("aa");
sb.append("a");
String str5 = sb.toString();

文章結尾

好了,JVM的基本原理就寫到這里,以后更深入的了解后會再來補充,

博主在這里給大家發個福利~
這里整理了20多家公司的真實面試經歷,以及各種關于Spring、Spring boot、Spring MVC、MyBatis、MySQL、JVM等知識點,如果有需要的小伙伴可以加群1149778920 來自行領取 暗號:CSDN
以下是部分資料截圖(所有資料均已整合成檔案,pdf壓縮打包處理),

在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/229158.html

標籤:java

上一篇:Java 進階:Java File & IO—1

下一篇:一篇了解什么是Spring AOP

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more