主頁 > 後端開發 > CPU飆高,頻繁GC,怎么排查?

CPU飆高,頻繁GC,怎么排查?

2020-10-23 07:45:44 後端開發

作者:愛寶貝丶
來源:my.oschina.net/zhangxufeng/blog/3017521

處理過線上問題的同學基本上都會遇到系統突然運行緩慢,CPU 100%,以及Full GC次數過多的問題,當然,這些問題的最終導致的直觀現象就是系統運行緩慢,并且有大量的報警,

本文主要針對系統運行緩慢這一問題,提供該問題的排查思路,從而定位出問題的代碼點,進而提供解決該問題的思路,

對于線上系統突然產生的運行緩慢問題,如果該問題導致線上系統不可用,那么首先需要做的就是,匯出jstack和記憶體資訊,然后重啟系統,盡快保證系統的可用性,這種情況可能的原因主要有兩種:

  • 代碼中某個位置讀取資料量較大,導致系統記憶體耗盡,從而導致Full GC次數過多,系統緩慢;

  • 代碼中有比較耗CPU的操作,導致CPU過高,系統運行緩慢;

相對來說,這是出現頻率最高的兩種線上問題,而且它們會直接導致系統不可用,另外有幾種情況也會導致某個功能運行緩慢,但是不至于導致系統不可用:

  • 代碼某個位置有阻塞性的操作,導致該功能呼叫整體比較耗時,但出現是比較隨機的;

  • 某個執行緒由于某種原因而進入WAITING狀態,此時該功能整體不可用,但是無法復現;

  • 由于鎖使用不當,導致多個執行緒進入死鎖狀態,從而導致系統整體比較緩慢,

對于這三種情況,通過查看CPU和系統記憶體情況是無法查看出具體問題的,因為它們相對來說都是具有一定阻塞性操作,CPU和系統記憶體使用情況都不高,但是功能卻很慢,下面我們就通過查看系統日志來一步一步甄別上述幾種問題,

1. Full GC次數過多

相對來說,這種情況是最容易出現的,尤其是新功能上線時,對于Full GC較多的情況,其主要有如下兩個特征:

  • 線上多個執行緒的CPU都超過了100%,通過jstack命令可以看到這些執行緒主要是垃圾回收執行緒

  • 通過jstat命令監控GC情況,可以看到Full GC次數非常多,并且次數在不斷增加,

首先我們可以使用top命令查看系統CPU的占用情況,如下是系統CPU較高的一個示例:

1.  `top -08:31:10 up 30 min,0 users,  load average:0.73,0.58,0.34`

2.  `KiBMem:2046460 total,1923864 used,122596 free,14388 buffers`

3.  `KiBSwap:1048572 total,0 used,1048572 free.1192352 cached Mem`

4.

5.  `  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND`

6.  `9 root      200255716028897615812 S  98.014.10:42.60 java`

可以看到,有一個Java程式此時CPU占用量達到了98.8%,此時我們可以復制該行程id9,并且使用如下命令查看呢該行程的各個執行緒運行情況:

top -Hp 9

該行程下的各個執行緒運行情況如下:

1.  `top -08:31:16 up 30 min,0 users,  load average:0.75,0.59,0.35`

2.  `Threads:11 total,1 running,10 sleeping,0 stopped,0 zombie`

3.  `%Cpu(s):3.5 us,0.6 sy,0.0 ni,95.9 id,0.0 wa,0.0 hi,0.0 si,0.0 st`

4.  `KiBMem:2046460 total,1924856 used,121604 free,14396 buffers`

5.  `KiBSwap:1048572 total,0 used,1048572 free.1192532 cached Mem`

6.

7.  `  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND`

8.  `10 root      200255716028982415872 R 79.314.20:41.49 java`

9.  `11 root      200255716028982415872 S 13.214.20:06.78 java`

可以看到,在行程為9的Java程式中各個執行緒的CPU占用情況,接下來我們可以通過jstack命令查看執行緒id為10的執行緒為什么耗費CPU最高,

推薦:jstack命令:教你如何排查多執行緒問題

需要注意的是,在jsatck命令展示的結果中,執行緒id都轉換成了十六進制形式,可以用如下命令查看轉換結果,也可以找一個科學計算器進行轉換:

root@a39de7e7934b:/# printf "%x\\n" 10a

這里列印結果說明該執行緒在jstack中的展現形式為0xa,通過jstack命令我們可以看到如下資訊:

1.  `"main"#1 prio=5 os_prio=0 tid=0x00007f8718009800 nid=0xb runnable [0x00007f871fe41000]`

2.  `   java.lang.Thread.State: RUNNABLE`

3.  `    at com.aibaobei.chapter2.eg2.UserDemo.main(UserDemo.java:9)`

5.  `"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable`

這里的VM Thread一行的最后顯示nid=0xa,這里nid的意思就是作業系統執行緒id的意思,而VM Thread指的就是垃圾回收的執行緒,這里我們基本上可以確定,當前系統緩慢的原因主要是垃圾回收過于頻繁,導致GC停頓時間較長,我們通過如下命令可以查看GC的情況:

root@8d36124607a0:/# jstat -gcutil 9 1000 10  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT  0.00   0.00   0.00  75.07  59.09  59.60   3259    0.919  6517    7.715    8.635  0.00   0.00   0.00   0.08  59.09  59.60   3306    0.930  6611    7.822    8.752  0.00   0.00   0.00   0.08  59.09  59.60   3351    0.943  6701    7.924    8.867  0.00   0.00   0.00   0.08  59.09  59.60   3397    0.955  6793    8.029    8.984

可以看到,這里FGC指的是Full GC數量,這里高達6793,而且還在不斷增長,從而進一步證實了是由于記憶體溢位導致的系統緩慢,那么這里確認了記憶體溢位,但是如何查看你是哪些物件導致的記憶體溢位呢,這個可以dump出記憶體日志,然后通過eclipse的mat工具進行查看,如下是其展示的一個物件樹結構:

經過mat工具分析之后,我們基本上就能確定記憶體中主要是哪個物件比較消耗記憶體,然后找到該物件的創建位置,進行處理即可,

這里的主要是PrintStream最多,但是我們也可以看到,其記憶體消耗量只有12.2%,也就是說,其還不足以導致大量的Full GC,此時我們需要考慮另外一種情況,就是代碼或者第三方依賴的包中有顯示的System.gc()呼叫,

這種情況我們查看dump記憶體得到的檔案即可判斷,因為其會列印GC原因:

\[Full GC (System.gc()) \[Tenured: 262546K->262546K(349568K), 0.0014879 secs\] 262546K->262546K(506816K), \[Metaspace: 3109K->3109K(1056768K)\], 0.0015151 secs\] \[Times: user=0.00 sys=0.00, real=0.01 secs\]\[GC (Allocation Failure) \[DefNew: 2795K->0K(157248K), 0.0001504 secs\]\[Tenured: 262546K->402K(349568K), 0.0012949 secs\] 265342K->402K(506816K), \[Metaspace: 3109K->3109K(1056768K)\], 0.0014699 secs\] \[Times: user=0.00

比如這里第一次GC是由于System.gc()的顯示呼叫導致的,而第二次GC則是JVM主動發起的,總結來說,對于Full GC次數過多,主要有以下兩種原因:

  • 代碼中一次獲取了大量的物件,導致記憶體溢位,此時可以通過eclipse的mat工具查看記憶體中有哪些物件比較多;

  • 記憶體占用不高,但是Full GC次數還是比較多,此時可能是顯示的 System.gc()呼叫導致GC次數過多,這可以通過添加 -XX:+DisableExplicitGC來禁用JVM對顯示GC的回應,

2. CPU過高

在前面第一點中,我們講到,CPU過高可能是系統頻繁的進行Full GC,導致系統緩慢,而我們平常也肯能遇到比較耗時的計算,導致CPU過高的情況,此時查看方式其實與上面的非常類似,

首先我們通過top命令查看當前CPU消耗過高的行程是哪個,從而得到行程id;然后通過top -Hp來查看該行程中有哪些執行緒CPU過高,一般超過80%就是比較高的,80%左右是合理情況,這樣我們就能得到CPU消耗比較高的執行緒id,接著通過該執行緒id的十六進制表示在jstack日志中查看當前執行緒具體的堆疊資訊,

在這里我們就可以區分導致CPU過高的原因具體是Full GC次數過多還是代碼中有比較耗時的計算了,如果是Full GC次數過多,那么通過jstack得到的執行緒資訊會是類似于VM Thread之類的執行緒,而如果是代碼中有比較耗時的計算,那么我們得到的就是一個執行緒的具體堆疊資訊,如下是一個代碼中有比較耗時的計算,導致CPU過高的執行緒資訊:

這里可以看到,在請求UserController的時候,由于該Controller進行了一個比較耗時的呼叫,導致該執行緒的CPU一直處于100%,我們可以根據堆疊資訊,直接定位到UserController的34行,查看代碼中具體是什么原因導致計算量如此之高,

3. 不定期出現的介面耗時現象

對于這種情況,比較典型的例子就是,我們某個介面訪問經常需要2~3s才能回傳,這是比較麻煩的一種情況,因為一般來說,其消耗的CPU不多,而且占用的記憶體也不高,也就是說,我們通過上述兩種方式進行排查是無法解決這種問題的,

而且由于這樣的介面耗時比較大的問題是不定時出現的,這就導致了我們在通過jstack命令即使得到了執行緒訪問的堆疊資訊,我們也沒法判斷具體哪個執行緒是正在執行比較耗時操作的執行緒,

對于不定時出現的介面耗時比較嚴重的問題,我們的定位思路基本如下:首先找到該介面,通過壓測工具不斷加大訪問力度,如果說該介面中有某個位置是比較耗時的,由于我們的訪問的頻率非常高,那么大多數的執行緒最終都將阻塞于該阻塞點,這樣通過多個執行緒具有相同的堆疊日志,我們基本上就可以定位到該介面中比較耗時的代碼的位置,如下是一個代碼中有比較耗時的阻塞操作通過壓測工具得到的執行緒堆疊日志:

1.  `"http-nio-8080-exec-2"#29 daemon prio=5 os_prio=31 tid=0x00007fd08cb26000 nid=0x9603 waiting on condition [0x00007000031d5000]`

2.  `   java.lang.Thread.State: TIMED_WAITING (sleeping)`

3.  `    at java.lang.Thread.sleep(NativeMethod)`

4.  `    at java.lang.Thread.sleep(Thread.java:340)`

5.  `    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)`

6.  `    at com.aibaobei.user.controller.UserController.detail(UserController.java:18)`

7.

8.  `"http-nio-8080-exec-3"#30 daemon prio=5 os_prio=31 tid=0x00007fd08cb27000 nid=0x6203 waiting on condition [0x00007000032d8000]`

9.  `   java.lang.Thread.State: TIMED_WAITING (sleeping)`

10.  `    at java.lang.Thread.sleep(NativeMethod)`

11.  `    at java.lang.Thread.sleep(Thread.java:340)`

12.  `    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)`

13.  `    at com.aibaobei.user.controller.UserController.detail(UserController.java:18)`

14.

15.  `"http-nio-8080-exec-4"#31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]`

16.  `   java.lang.Thread.State: TIMED_WAITING (sleeping)`

17.  `    at java.lang.Thread.sleep(NativeMethod)`

18.  `    at java.lang.Thread.sleep(Thread.java:340)`

19.  `    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)`

20.  `at com.aibaobei.user.controller.UserController.detail(UserController.java:18)`

從上面的日志可以看你出,這里有多個執行緒都阻塞在了UserController的第18行,說明這是一個阻塞點,也就是導致該介面比較緩慢的原因,

4. 某個執行緒進入WAITING狀態

對于這種情況,這是比較罕見的一種情況,但是也是有可能出現的,而且由于其具有一定的“不可復現性”,因而我們在排查的時候是非常難以發現的,

筆者曾經就遇到過類似的這種情況,具體的場景是,在使用CountDownLatch時,由于需要每一個并行的任務都執行完成之后才會喚醒主執行緒往下執行,而當時我們是通過CountDownLatch控制多個執行緒連接并匯出用戶的gmail郵箱資料,這其中有一個執行緒連接上了用戶郵箱,但是連接被服務器掛起了,導致該執行緒一直在等待服務器的回應,最終導致我們的主執行緒和其余幾個執行緒都處于WAITING狀態,

推薦:一張圖弄懂java執行緒的狀態和生命周期

對于這樣的問題,查看過jstack日志的讀者應該都知道,正常情況下,線上大多數執行緒都是處于TIMED_WAITING狀態,而我們這里出問題的執行緒所處的狀態與其是一模一樣的,這就非常容易混淆我們的判斷,解決這個問題的思路主要如下:

  • 通過grep在jstack日志中找出所有的處于 TIMED_WAITING狀態的執行緒,將其匯出到某個檔案中,如a1.log,如下是一個匯出的日志檔案示例:
"Attach Listener" #13 daemon prio=9 os\_prio=31 tid=0x00007fe690064000 nid=0xd07 waiting on condition \[0x0000000000000000\]"DestroyJavaVM" #12 prio=5 os\_prio=31 tid=0x00007fe690066000 nid=0x2603 waiting on condition \[0x0000000000000000\]"Thread-0" #11 prio=5 os\_prio=31 tid=0x00007fe690065000 nid=0x5a03 waiting on condition \[0x0000700003ad4000\]"C1 CompilerThread3" #9 daemon prio=9 os\_prio=31 tid=0x00007fe68c00a000 nid=0xa903 waiting on condition \[0x0000000000000000\]
  • 等待一段時間之后,比如10s,再次對jstack日志進行grep,將其匯出到另一個檔案,如a2.log,結果如下所示:
"DestroyJavaVM" #12 prio=5 os\_prio=31 tid=0x00007fe690066000 nid=0x2603 waiting on condition \[0x0000000000000000\]"Thread-0" #11 prio=5 os\_prio=31 tid=0x00007fe690065000 nid=0x5a03 waiting on condition \[0x0000700003ad4000\]"VM Periodic Task Thread" os_prio=31 tid=0x00007fe68d114000 nid=0xa803 waiting on condition
  • 重復步驟2,待匯出34個檔案之后,我們對匯出的檔案進行對比,找出其中在這幾個檔案中一直都存在的用戶執行緒,這個執行緒基本上就可以確認是包含了處于等待狀態有問題的執行緒,因為正常的請求執行緒是不會在2030s之后還是處于等待狀態的,

  • 經過排查得到這些執行緒之后,我們可以繼續對其堆疊資訊進行排查,如果該執行緒本身就應該處于等待狀態,比如用戶創建的執行緒池中處于空閑狀態的執行緒,那么這種執行緒的堆疊資訊中是不會包含用戶自定義的類的,這些都可以排除掉,而剩下的執行緒基本上就可以確認是我們要找的有問題的執行緒,通過其堆疊資訊,我們就可以得出具體是在哪個位置的代碼導致該執行緒處于等待狀態了,

這里需要說明的是,我們在判斷是否為用戶執行緒時,可以通過執行緒最前面的執行緒名來判斷,因為一般的框架的執行緒命名都是非常規范的,我們通過執行緒名就可以直接判斷得出該執行緒是某些框架中的執行緒,這種執行緒基本上可以排除掉,而剩余的,比如上面的Thread-0,以及我們可以辨別的自定義執行緒名,這些都是我們需要排查的物件,

經過上面的方式進行排查之后,我們基本上就可以得出這里的Thread-0就是我們要找的執行緒,通過查看其堆疊資訊,我們就可以得到具體是在哪個位置導致其處于等待狀態了,如下示例中則是在SyncTask的第8行導致該執行緒進入等待了,

"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition \[0x0000700001f89000\]   java.lang.Thread.State: WAITING (parking)    at sun.misc.Unsafe.park(Native Method)    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)    at com.aibaobei.chapter2.eg4.SyncTask.lambda$main$0(SyncTask.java:8)    at com.aibaobei.chapter2.eg4.SyncTask$Lambda$1/1791741888.run(Unknown Source)    at java.lang.Thread.run(Thread.java:748)

5. 死鎖

對于死鎖,這種情況基本上很容易發現,因為jstack可以幫助我們檢查死鎖,并且在日志中列印具體的死鎖執行緒資訊,如下是一個產生死鎖的一個jstack日志示例:

可以看到,在jstack日志的底部,其直接幫我們分析了日志中存在哪些死鎖,以及每個死鎖的執行緒堆疊資訊,這里我們有兩個用戶執行緒分別在等待對方釋放鎖,而被阻塞的位置都是在ConnectTask的第5行,此時我們就可以直接定位到該位置,并且進行代碼分析,從而找到產生死鎖的原因,

6. 小結

本文主要講解了線上可能出現的五種導致系統緩慢的情況,詳細分析了每種情況產生時的現象,已經根據現象我們可以通過哪些方式定位得到是這種原因導致的系統緩慢,簡要的說,我們進行線上日志分析時,主要可以分為如下步驟:

  • 通過 top命令查看CPU情況,如果CPU比較高,則通過 top-Hp<pid>命令查看當前行程的各個執行緒運行情況,找出CPU過高的執行緒之后,將其執行緒id轉換為十六進制的表現形式,然后在jstack日志中查看該執行緒主要在進行的作業,這里又分為兩種情況

  • 如果是正常的用戶執行緒,則通過該執行緒的堆疊資訊查看其具體是在哪處用戶代碼處運行比較消耗CPU;

  • 如果該執行緒是 VMThread,則通過 jstat-gcutil<pid><period><times>命令監控當前系統的GC狀況,然后通過 jmapdump:format=b,file=<filepath><pid>匯出系統當前的記憶體資料,匯出之后將記憶體情況放到eclipse的mat工具中進行分析即可得出記憶體中主要是什么物件比較消耗記憶體,進而可以處理相關代碼;

  • 如果通過 top 命令看到CPU并不高,并且系統記憶體占用率也比較低,此時就可以考慮是否是由于另外三種情況導致的問題,具體的可以根據具體情況分析:

  • 如果是介面呼叫比較耗時,并且是不定時出現,則可以通過壓測的方式加大阻塞點出現的頻率,從而通過 jstack查看堆疊資訊,找到阻塞點;

  • 如果是某個功能突然出現停滯的狀況,這種情況也無法復現,此時可以通過多次匯出 jstack日志的方式對比哪些用戶執行緒是一直都處于等待狀態,這些執行緒就是可能存在問題的執行緒;

  • 如果通過 jstack可以查看到死鎖狀態,則可以檢查產生死鎖的兩個執行緒的具體阻塞點,從而處理相應的問題,

本文主要是提出了五種常見的導致線上功能緩慢的問題,以及排查思路,當然,線上的問題出現的形式是多種多樣的,也不一定局限于這幾種情況,如果我們能夠仔細分析這些問題出現的場景,就可以根據具體情況具體分析,從而解決相應的問題,

推薦去我的博客閱讀更多:

1.Java JVM、集合、多執行緒、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、后端、架構、阿里巴巴等大廠最新面試題

覺得不錯,別忘了點贊+轉發哦!

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

標籤:Java

上一篇:用java制作一款完善的貪吃蛇游戲

下一篇:教你在 IntelliJ IDEA 中使用 VIM!

標籤雲
其他(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