主頁 > 後端開發 > jvm中類和物件定義存盤基礎知識

jvm中類和物件定義存盤基礎知識

2023-06-08 07:57:25 後端開發

1 類檔案資料結構型別

Class檔案結構主要有兩種資料結構:無符號數和表

?無符號數:用來表述數字,索引參考、數量值以及字串等,比如 圖1中型別為u1,u2,u4,u8分別代表1個位元組,2個位元組,4個位元組,8個位元組的無符號數

?:表是有由多個無符號數以及其它的表組成的復合結構,比如圖1中型別以_info結尾的項為表型別,

2 類結構定義

Class類檔案是緊湊、順序、無空隙的,魔數(MagicNumber)、Class檔案版本(Version)、常量池(Constant_Pool)、訪問標記(Access_flag)、本類(This_class)、父類(Super_class)、介面(Interfaces)、欄位集合(Fields)、方法集合(Methods )、屬性集合(Attributes),其中因為java多繼承所以interfaces介面型別為陣列;attribute_info則是方法表中定義的code索引,指向具體的方法體位元組碼,如圖1所示,

下面用一段程式做說明,此類有介面,有方法、類變數和實體變數,機器是如何識別位元組碼然后按照上面的規則來定義此class類呢?

package com.jd.crm.Logback;

public class TestClass implements Super{

    private static final int staticVar = 0;

    private int instanceVar=0;

    public int instanceMethod(int param) throws  Exception{
        return param ++;
    }
}
interface Super{ }

通過javap幫助決議class檔案格式如下:

Classfile /D:/spm-workspace/test/target/classes/com/jd/crm/Logback/TestClass.class
  Last modified 2023-4-14; size 597 bytes
  MD5 checksum 9d5dd9fc2145ac17393fee7a707d3b9c
  Compiled from "TestClass.java"
public class com.jd.crm.Logback.TestClass implements com.jd.crm.Logback.Super
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#26         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#27         // com/jd/crm/Logback/TestClass.instanceVar:I
   #3 = Class              #28            // com/jd/crm/Logback/TestClass
   #4 = Class              #29            // java/lang/Object
   #5 = Class              #30            // com/jd/crm/Logback/Super
   #6 = Utf8               staticVar
   #7 = Utf8               I
   #8 = Utf8               ConstantValue
   #9 = Integer            0
  #10 = Utf8               instanceVar
  #11 = Utf8               <init>
  #12 = Utf8               ()V
  #13 = Utf8               Code
  #14 = Utf8               LineNumberTable
  #15 = Utf8               LocalVariableTable
  #16 = Utf8               this
  #17 = Utf8               Lcom/jd/crm/Logback/TestClass;
  #18 = Utf8               instanceMethod
  #19 = Utf8               (I)I
  #20 = Utf8               param
  #21 = Utf8               Exceptions
  #22 = Class              #31            // java/lang/Exception
  #23 = Utf8               MethodParameters
  #24 = Utf8               SourceFile
  #25 = Utf8               TestClass.java
  #26 = NameAndType        #11:#12        // "<init>":()V
  #27 = NameAndType        #10:#7         // instanceVar:I
  #28 = Utf8               com/jd/crm/Logback/TestClass
  #29 = Utf8               java/lang/Object
  #30 = Utf8               com/jd/crm/Logback/Super
  #31 = Utf8               java/lang/Exception
{
  public com.jd.crm.Logback.TestClass();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_0
         6: putfield      #2                  // Field instanceVar:I
         9: return
      LineNumberTable:
        line 3: 0
        line 7: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lcom/jd/crm/Logback/TestClass;

  public int instanceMethod(int) throws java.lang.Exception;
    descriptor: (I)I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=2, args_size=2
         0: iload_1
         1: iinc          1, 1
         4: ireturn
      LineNumberTable:
        line 10: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/jd/crm/Logback/TestClass;
            0       5     1 param   I
    Exceptions:
      throws java.lang.Exception
    MethodParameters:
      Name                           Flags
      param
}
SourceFile: "TestClass.java"

以上是javap幫助我們生成的class檔案決議結果,只是給人看,而非機器,

通過編譯后生成class檔案格式如下,因為class檔案是以8位作為一個位元組的二進制流,為了方便計算,用16進制表示二進制(1個位元組=2個十六進制的數,故下面每2個數就代表1個位元組)

2.1 魔法數

前四個位元組cafebabe是固定值,任何語言編譯成jvm認識的二進制流,前四位必須是固定的cafebabe位元組,

2.2 版本號

緊接著2個位元組00表示次版本號為0 ;0034代表主版本為52(jdk版本號對應的jdk版本為1.8)參考jdk版本和class位元組版本的對應關系

2.3 常量個數

常量個數const_pool_count位元組碼為00 20對應的說明常量個數為32,實際為31個,因為首位jvm作為保留位使用,

2.4 常量池

常量池存放兩大常量:字面量和符號引,字面量如文本字串,被生命的final常量值等,而符號參考則包含類、介面的全限名稱、欄位、方法名稱和描述符號等等,參考javap生成的類檔案資訊,

這里只分析下其中一個常量,在上面常量個數2個位元組后面緊接著一個位元組0a十進制為10,參考常量池型別10代表類中方法的符號參考,繼續參考方法型別MethodRef_info個格式定義:前兩個位元組0004代表方法所在類名稱的索引,后兩個位元組0001a代表一個NameAndType型別的索引,

2.5 類訪問標志

緊接常量池定義完后的u2標識訪問標志,本例標識為0x0021和下圖示志位按位或計算,如0x0001為真,0x0020也為真,其他為否 最終確認訪問標志位ACC_PUBLIC、ACC_SUPER

2.6 本類、父類、介面索引集合

根據圖1的規則,u2兩個位元組0003標識當前類名的參考到,參考常量池陣列下標為#3,根據圖3所示子項的類名為com/jd/crm/Logback/TestClass;0004代表父類類名的參考常量池陣列下標為#4,根據圖4所示參考的父類類名為java/lang/Object;緊接著0001標識介面個數,指明數量為1,0005標識第一個介面陣列中介面的名稱,指向常量池中下標為5的名稱為com/jd/crm/Logback/Super;

比如查找當前類索引如下圖

2.7 欄位表集合

欄位表以陣列的形式定義存盤在常量表中

以上圖說明,0002標識域個數為2個域標識,在本類中有兩個,一個類的域欄位staticVar 一個是實體物件的域欄位instanceVar,如欄位結構定義(下圖)定義,前2個位元組001a為訪問標識,和類訪問標識一樣,分別用001a的二進制和下圖欄位域訪問標識型別做位或運算,得出訪問型別為ACC_PRIVATE型別,name_index的占用兩個位元組0006,指向常量表下標為6的參考,descriptor_index=0007指向常量表下標為7的參考,此處為I標識為資料型別為int,attributes_count=0001為1個,值為0008指向常量表下標為#8的參考常量ConstantValue,標識為靜態變數,最終依次類推第二個域標識參考

欄位結構定義

欄位域的訪問標志請參考類訪問標志,邏輯計算一致,只是規則不一樣而已 如下圖

2.8 方法表集合

和域欄位集合表定義類似 也是陣列方式定義在常量池中 ,其中方法的結構體第四個欄位attributes_count代表方法的屬性數量,attribute_info就是屬性的集合參考屬性表集合

方法表訪問標識型別

通過上面方法的訪問標志、名稱索引和描述索引定義方法的基本資訊,方法的代碼塊則存放于型別為Code的屬性表中,

2.9 屬性表集合

類、欄位表、方法表本身可包含屬性表,屬性表格結構體如下,屬性表結構型別較多,比如有Code型別、Exception型別、MethodParameters型別等等,具體參考屬性表型別,所有的屬性都是參考常量池中的屬性型別名稱,然后根據屬性的長度指定該屬性的內容,根據屬性的不同型別決議不同的屬性值,格式定義如下

以Code屬性舉例,Code屬性結構如下所示

jvm按屬性獲取attribute_name_index指向常量池一個字串常量Code,緊接著attribute_length標識Code型別Info資訊長度,這個info內容包括:max_stack 最大堆疊深,max_locals區域變數槽數量,code_length標識機器位元組碼長度,往后查詢位元組碼如下圖所示,其實就是0/1/4/5/6/9的指令集,Code型別又嵌套例外屬性表、行號表LineNumberTable、LocaVariableTable 區域變數表等等資訊,如下圖javap生成的類定義資訊

1.Code1方法執行程序:

構造方法:descriptor ()V標識無參無回傳值為Void的方法索引,flags可見性修飾符;

程式運行時,先將常量池、方法位元組碼、字串常量池,靜態變數加載到元資料區(1.8后字串常量池,靜態變數放入了堆);main執行緒開始運行,分配堆疊幀記憶體,其中運算元堆疊stack=2表示運行該方法所需要的最大運算元堆疊的深度是2;locals=1表示該運行方法所需要的最大區域方法表的最大slot資料是1;args_size是該方法的形參個數,如果是實體方法 第一個形參是this參考,此例正是this參考,所以args_size=1+實際的引數

aload_0: 加載 slot0的區域變數,即this,作為下面的invokespecial 構造方法呼叫的引數

invokespecial: 呼叫構造方法,常量池第#1項,即【Method java/lang/Object.""??)V】

aload_0 :再次加載 slot0的區域變數,即this

iconst0: 將int型別為0的數值壓入堆疊頂(為什么要再放入堆疊頂,我個人人為可能是下面初始化實體會需要指定到當前的實體物件)

putfileld: 將常量池中#2 也就是com/jd/crm/Logback/TestClass.instanceVar 實體變數賦值為0,并彈出堆疊,

通過以上指令操作,物件已經初始化,可發現在實體變數初始化之前是先呼叫的構造器方法,后才初始化實體變數,

1.Code2方法instanceMethod執行程序:

descriptor標識為int型別入參、int型別出參

flags標識方法問public型別

statck=2代表堆疊深度為2,locals=2標識預留兩個區域變數槽;args_size=2標識兩個引數,分別為隱藏的this和方法的形式引數,下標[0]=this、 [1]=param 如下所示

LocalVariableTable:

Start Length Slot Name Signature

0 4 0 this Lcom/jd/crm/Logback/TestClass;

0 4 1 param I

0:iload_1 標識將上面區域變數槽LocalVariableTable下標為1的param引數壓入堆疊

1:iconst_1 將int型別為1的常量數字壓入堆疊

2: iadd 將當前堆疊頂的兩個元素 param和1相加

3: ireturn 回傳

LineNumberTable:

line 10: 0

標識實際java源代碼的行數

2.10 位元組碼指令簡介

?加載和存盤指令:

?運算指令

?型別轉換指令

?物件創建和訪問指令

?運算元堆疊管理指令

?控制轉移指令

?例外處理指令

?同步指令

?方法呼叫和回傳執行

invokervirtual:呼叫物件的實體方法 invokerinterface 呼叫介面方法,自動運行期搜索一個實作介面的物件進行方法呼叫;invokerspeical:呼叫init、私有和父類呼叫的特殊方法呼叫;invokedynamic:運行時動態決議

3 類檔案加載

3.1 加載

jvm通過classLoader(雙親委派)將class類檔案二進制流加載到元資料區記憶體,

將位元組流所標識的靜態存盤結構轉換為元資料區的動態存盤

在堆記憶體創建一個Class物件,堆中的Class并不存盤靜態變數、常量、方法等實際資訊(實際存盤元空間),可以看做只是一個句柄,通過物件頭的類指標指向元空間類資訊,這樣在強制轉換或者InstanceOf判斷時,會根據物件中的類指標指向元空間的類常量池進行判斷是否為同一個類,

3.2 驗證

1、檔案格式驗證

2、元資料驗證

3、位元組碼驗證

4、符號參考驗證

3.3 準備

準備階段是為類變數(靜態變數)分配記憶體并設定類變數初始值的階段,分配這些記憶體是在元資料區里面進行的,但是類變數(無final修飾的靜態變數)、字串常量在1.8及以后都放入了堆區間,這個階段有兩點需要重點介紹以下的:

1、只有類變數(被static修飾的變數賦值初始值,static final修飾的賦值為程式指定值)會分配記憶體,不包括實體變數,實體變數是在物件實體化的時候在堆中分配記憶體的,

2、設定類變數的初始值是數量型別對應的默認值,而不是代碼中設定的默認值,例如public static int number=111,這類變數number在準備階段之后的初始值是0而不是111,而給number賦值為111是在類的初始化階段,

3.4 決議

決議階段是虛擬機將常量池內的符號參考替換為直接參考的程序,決議動作主要針對類或介面、欄位、類方法、介面方法、方法型別、方法句柄和呼叫點限定符7類符號參考進行,

符號參考:常量池中類、欄位的常量字串表示方式

類和介面的決議舉例:假如類A參考了類B,加載階段是靜態決議,這時候B還沒有被放到JVM記憶體中,這時候A參考的只是代表B的符號,這是符號參考,

直接參考: 指向目標的指標或者相對偏移量

類和介面的決議舉例:類A在決議階段發現自己符號參考了B,如果這個時候B還沒被加載,就是直接觸發B的類加載,加載后會在運行常量池存盤B的有效類資訊地址,并且直接參考,

?類和介面的決議

?欄位決議根據常量池欄位filedrf_info中的符號進行決議,首先在符號參考的類中根據簡單名稱和欄位描述符查找,如果查到則回傳這個欄位的直接參考并結束,否則從下往上地柜各個父類查找,如果還未查到則拋出NoSuckFieldError例外

?方法決議

?介面方法決議

4 類實體初始化

初始化,為類的靜態變數賦予正確的初始值,JVM負責對類進行初始化,主要對類變數進行初始化clinit方法,在Java中對類變數進行初始值設定有兩種方式:定義靜態變數并指定值、使用靜態代碼塊

物件初始化

4.1 初始化物件前檢查

jvm碰到一個new指令,首先判斷改指令指向的常量池的類全名是否被加載、決議初始化過,如果沒有則進行類加載,參考類檔案加載

4.2 記憶體分配

通過jvm記憶體分配機制,此分配機制取決回識訓制,通過指標碰撞方法或者空閑串列方式進行堆記憶體分配;

1.指標碰撞法 假設Java堆中記憶體是完整的,已分配的記憶體和空閑記憶體分別在不同的一側,通過一個指標作為分界點,需要分配記憶體時,僅僅需要把指標往空閑的一端移動與物件大小相等的距離,使用的GC收集器:Serial、ParNew,適用堆記憶體規整(即沒有記憶體碎片)的情況下,這兩種都是新生代垃圾收集器,因此都是使用復制演算法,可以得到比較完整的記憶體區域,

2.空閑串列法 事實上,Java堆的記憶體并不是完整的,已分配的記憶體和空閑記憶體相互交錯,JVM通過維護一個串列,記錄可用的記憶體塊資訊,當分配操作發生時,從串列中找到一個足夠大的記憶體塊分配給物件實體,并更新串列上的記錄,使用的GC收集器:CMS,適用堆記憶體不規整的情況下,從名字中的Mark Sweep這兩個詞可以看出,CMS 收集器是一種“標記-清除”演算法實作的,因此會得到很多碎片因此和空閑串列配合使用,

記憶體分配并發問題

在創建物件的時候有一個很重要的問題,就是執行緒安全,因為在實際開發程序中,創建物件是很頻繁的事情,作為虛擬機來說,必須要保證執行緒是安全的,通常來講,虛擬機采用兩種方式來保證執行緒安全:

?CAS: CAS 是樂觀鎖的一種實作方式,所謂樂觀鎖就是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止,虛擬機采用 CAS 配上失敗重試的方式保證更新操作的原子性,

?TLAB(本地現成緩沖區): 為每一個執行緒預先分配一塊堆記憶體,JVM在給執行緒中的物件分配記憶體時,首先在TLAB分配,當物件大于TLAB中的剩余記憶體或TLAB的記憶體已用盡時,再采用上述的CAS進行記憶體分配,

4.3 初始化0值

記憶體分配完成后,虛擬機需要將分配到的記憶體空間都初始化為零值(不包括物件頭),這一步操作保證了物件的實體欄位在 Java 代碼中可以不賦初始值就直接使用,程式能訪問到這些欄位的資料型別所對應的零值,

4.4 物件頭設定

初始化零值完成之后,虛擬機要對物件進行必要的設定,例如這個物件是哪個類的實體、如何才能找到類的元資料資訊、物件的哈希碼、物件的 GC 分代年齡等資訊,這些資訊存放在物件頭中,另外,根據虛擬機當前運行狀態的不同,如是否啟用偏向鎖等,物件頭會有不同的設定方式,

4.5 實體構造器初始化

4.6 物件的記憶體布局

物件在對中的存盤布局主要分為三部分,物件頭、實體資料、對齊填充

物件頭:

主要兩類:其主要包括兩部分資料:Mark Word、Class物件指標,特別地對于陣列物件而言,其還包括了陣列長度資料,在64位的HotSpot虛擬機下,Mark Word占8個位元組,其記錄了Hash Code、GC資訊、鎖資訊等相關資訊;而Class物件指標則指向該實體的Class物件,

HotSpot物件頭

實體資料:物件定義的實體變數,這部分資料存盤受到虛擬機分配策略引數(-XX:FieldsAllocationStype)和欄位定義的順序影響,HotSpot默認分配的策略是將相同寬度欄位一起存放,父類的變數會出現在子類變數之前,

對齊填充:jvm存盤任何大小必須是8個位元組的整數倍,不夠補齊,這個和類二級制位元組流一致,下面是個無鎖狀態的物件實體化后的資料結構,使用jol工具列印出的實體布局如下

5 物件的訪問

5.1 句柄訪問

Java堆中將會劃分出一塊記憶體來作為句柄池,reference中 存盤的就是物件

的句柄地址,而句柄中包含了物件實體資料與型別資料各自的具體地址信 息

5.2 直接訪問

直接訪問是reference中直接存盤的實體物件的地址,實體物件中包含了類物件的訪問指標,也就是如果訪問類物件需要多一層參考

優缺點

這兩種物件訪問方式各有優勢,使用句柄來訪問的最大好處就是reference中存盤的是穩定的句柄地址,在物件被移動(垃圾收集時移動物件是非常普遍的行為)時只會改變句柄中的實體資料指標,而reference本身不需要修改, 使用直接指標訪問方式的最大好處就是速度更快,它節省了一次指標定位的時間開銷, 由于物件的訪問在Java中非常頻繁,因此這類開銷積少成多后也是一項非常可觀的執行成本,就本書討論的主要虛擬機Sun HotSpot而言,它是使用第二種方式進行物件訪問的,但從整個軟體開發的范圍來看,各種語言和框架使用句柄來訪問的情況也十分常見

6 虛擬機位元組碼執行引擎

6.1 運行時堆疊幀結構

1.區域變數表:在class檔案被編譯時,就已知某個方法的區域變數槽有幾個,主要存放方法引數和方法內部定義的區域變數

2.運算元堆疊:和區域變數表相似,編譯時就明確了運算元堆疊的深度

3.動態鏈接:大部分類在類加載決議程序中,會將符號參考轉為直接參考,也就是在類加載階段清楚呼叫哪個類的哪個方法(這些方法呼叫參考位元組碼指令簡介中invoke*指令),但是有一部分必須在運行期間才能確定目標的方法的直接參考,

4.方法回傳地址

6.2 方法呼叫

1.決議:在內決議階段,會將符號參考轉換為直接參考,這種在決議階段就能確定的呼叫方法版本稱為決議,比如invokesatic invokespecial invokevirtual等等指令指示的方法呼叫

2.靜態分派:方法的多載,虛擬機需要根據方法的入參個數和型別方能定位到某個具體方法,發生在編譯階段,故也屬于一種決議方式

3.多載方法匹配優先級:方法多載程序中,涉及方法的入參和個數,而入參存在自動型別轉換,比如多載方法入參為char型別,如果不存在入參為char型別的方法匹配,則char進行自動型別轉換為int型別,在最終匹配了Int入參型別的方法,方法多載的本質

4.動態分配:如下圖所示,man和women和重新man參考指向women然后方法呼叫sayHello,此時位元組碼顯示的符號參考都是Human#sayHello,但是實際執行結果和指令碼不一致,這是因為invokevirtual指令,在指令呼叫之前都會aload_x來加載實際的資料型別,這就是方法重寫的本質

5.invokedynamic指令:為了解決其他invok*指令方法分配規則完全固化在虛擬機中的問題,jvm支持設計者更高的靈活度,將動態呼叫可以以api的方式直接使用,參考java.lang.invoke包的使用方式,

6.3 基于堆疊的位元組碼解釋執行引擎

jvm是基于堆疊的指令集合,這種指令自身不帶引數,使用運算元堆疊的輸入輸出作為指令本身的引數,物理機一般是基于暫存器的指令集,指令本身攜帶引數并存放在暫存器,

下面是一個基于堆疊來展示在虛擬機中位元組碼是如何執行的,

以上位元組碼執行程序如下

7 容易混淆點

7.1 檔案常量池

類加載后,類的域欄位、方法和類描述資訊會加載到元資料區,既屬于類的靜態常量池

7.2 運行時常量池

我們上面說的class檔案中的常量池,它會在類加載后進入方法區中的運行時常量池,并非只有Class定義的檔案常量合并處理后放入運行時常量池,在運行期間也可以將新的常量放入池中,比如String類的intern方法

7.3 字串常量池

字串常量池存放在堆記憶體(>=1.8)中,堆里邊的字串常量池存放的是字串的參考或者字串(兩者都有),如下圖描述字串創建的堆分布

上圖說明:

參考初始化初始化s、s2是先看常量池,有就回傳物件參考,否則創建abc物件,然后創建s1/s2Ref常量參考回傳

字串相加:先創建StringBuilder物件,然后apend字串a、apend字串b 然后toString(new方法)生成字串ab物件并在字串常量池生成參考回傳,為什么不要字串相加,就是因為會生成大量StringBuilder物件

String s = "a"+"b";//回傳的是常量池的ab字串的參考
String s1 ="ab";
System.out.println(s == s1);//因兩個最終都指向字串常量池,所以為true

new 字串相當于堆創建兩個物件,一個String物件,然后創建字串堆存盤,然后String物件參考到字串的堆存盤,

String s1 ="a";
String s = new String ("a").intern();//強制生成字串常量池參考
System.out.println(s == s1);//回傳true

String s1 ="a";
String s = new String ("a");
System.out.println(s == s1);//回傳false

8 附件

jvm常量池型別和結構體定義

常量池型別

常量池型別結構定義

常見的屬性型別

jdk版本好class位元組版本號對應關系

屬性表型別

作者:京東物流 王北永

來源:京東云開發者社區

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

標籤:其他

上一篇:【python基礎】回圈陳述句-while回圈

下一篇:返回列表

標籤雲
其他(160516) Python(38215) JavaScript(25478) Java(18209) C(15237) 區塊鏈(8270) C#(7972) AI(7469) 爪哇(7425) MySQL(7235) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4585) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2434) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1983) 功能(1967) HtmlCss(1952) Web開發(1951) C++(1933) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1879) .NETCore(1863) 谷歌表格(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
最新发布
  • jvm中類和物件定義存盤基礎知識

    在Java虛擬機中,類和物件是程式的基本組成單元。類定義了一組物件的共性特征和行為,是Java程式中最基本的代碼單元。而物件則是具體的實體,有自己獨特的狀態和行為。在JVM中,類和物件都需要進行存盤,因此了解類和物件的存盤基礎知識對于Java程式員來說是非常重要的。 ......

    uj5u.com 2023-06-08 07:57:25 more
  • 【python基礎】回圈陳述句-while回圈

    # 1.初識while回圈 回圈陳述句主要的作用是在多次處理具有相同邏輯的代碼時使用。while回圈是Python提供的回圈陳述句之一。 while回圈的語法格式之一: ![image](https://img2023.cnblogs.com/blog/3179433/202306/3179433-20 ......

    uj5u.com 2023-06-08 07:57:14 more
  • spring cloud gateway網關(一)之網關路由

    1、gateway相關介紹 在微服務架構中,系統往往由多個微服務組成,而這些服務可能部署在不同機房、不同地區、不同域名下。這種情況下,客戶端(例如瀏覽器、手機、軟體工具等)想要直接請求這些服務,就需要知道它們具體的地址資訊,例如 IP 地址、埠號等。這種客戶端直接請求服務的方式存在很多的復雜問題。 ......

    uj5u.com 2023-06-08 07:56:58 more
  • 深入理解注解驅動配置與XML配置的融合與區別

    摘要:本文旨在深入探討Spring框架的注解驅動配置與XML配置,揭示兩者之間的相似性與差異。 本文分享自華為云社區《Spring高手之路2——深入理解注解驅動配置與XML配置的融合與區別》,作者:磚業洋__ 。 本文旨在深入探討Spring框架的注解驅動配置與XML配置,揭示兩者之間的相似性與差異 ......

    uj5u.com 2023-06-08 07:56:35 more
  • 【python爬蟲實戰】用python爬取愛奇藝電視劇十大榜單的全部資料

    [toc] # 一、爬取目標 本次爬取的目標是,愛奇藝電視劇類目下的10個榜單:[電視劇風云榜-愛奇藝風云榜](https://www.iqiyi.com/ranks1/2/0) ?![愛奇藝頁面](https://img2023.cnblogs.com/blog/2864563/202306/28 ......

    uj5u.com 2023-06-08 07:55:31 more
  • 【Python&RS】遙感影像的像素坐標轉地理坐標(仿射變換)

    ? GDAL(Geospatial Data Abstraction Library)是一個在X/MIT許可協議下的開源柵格空間資料轉換庫。它利用抽象資料模型來表達所支持的各種檔案格式。它還有一系列命令列工具來進行資料轉換和處理。 Python的GDAL庫作為柵格資料的處理轉換庫,其支持幾百種柵格數 ......

    uj5u.com 2023-06-08 07:55:17 more
  • Python&Excel辦公自動化

    操作作業簿 01 新建一個excel作業簿 #2023-4-17 import xlwings as xw # 啟動 excel,但不新建作業簿 app是什么,app是excel程式本身 app = xw.App(visible=True,add_book=True) #新建一個作業簿 workbo ......

    uj5u.com 2023-06-08 07:55:12 more
  • Python 串列推導式:簡潔、高效的資料操作藝術

    # Python 串列推導式:簡潔、高效的資料操作藝術 Python 的串列推導式,這個看似簡單的語法糖,實則內含無限威力。在 Python 代碼撰寫中,串列推導式的靈活性和簡潔性讓它成為了不可或缺的一部分。在這篇文章中,我們將更全面、更深入地探討串列推導式,從基礎的概念認識,到各類進階的用法和操作 ......

    uj5u.com 2023-06-08 07:55:07 more
  • 鏈家廣州二手房資料 2023

    還記得在2019年的夏天曾經用 R 爬過一份廣州在 lianjia.com 放盤資料 ([博客1](https://www.cnblogs.com/yukiwu/p/10975337.html),[博客2](https://www.cnblogs.com/yukiwu/p/11271515.html ......

    uj5u.com 2023-06-08 07:55:01 more
  • 【python基礎】回圈陳述句-while回圈

    # 1.初識while回圈 回圈陳述句主要的作用是在多次處理具有相同邏輯的代碼時使用。while回圈是Python提供的回圈陳述句之一。 while回圈的語法格式之一: ![image](https://img2023.cnblogs.com/blog/3179433/202306/3179433-20 ......

    uj5u.com 2023-06-08 07:54:50 more