18video性欧美19sex,欧美高清videosddfsexhd,性少妇videosexfreexxx片中国,激情五月激情综合五月看花,亚洲人成网77777色在线播放

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

頻繁FullGC的原因竟然是開源代碼?

OSC開源社區(qū) ? 來源:OSCHINA 社區(qū) ? 2023-07-30 15:56 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

首先 java 語言的特性是不需像 C 和 C++ 那樣自己手動釋放內(nèi)存,因為 java 本身有垃圾回收機制(垃圾回收稱為 GC),顧名思義就是釋放垃圾占用的空間,防止內(nèi)存泄露。JVM 運行時占用內(nèi)存最大的空間就是堆內(nèi)存,另外棧區(qū)和方法區(qū)也會占用空間但是占用有限本章就不探究了。

那么堆中的空間又分為年輕代和老年代,所以我們粗略的把垃圾回收分為兩種:年輕代的垃圾回收稱為 Young GC,老年代的垃圾回收稱為 Full GC,實際上此處的 Full GC 也包含了新生代,老年代,元空間等的回收。 因為 Full GC 的回收過程會使系統(tǒng)的所有線程 STW(Stop The World),那么我們一定希望讓系統(tǒng)盡量不要進行 Full GC,或者必須要進行 FullGC 的時候執(zhí)行的時間越短越好。

下面我們主要探究 Full GC 的角度出發(fā)分析我在開發(fā)運營后臺的時候遇到的頻繁 Full GC 過程。

事件背景

項目介紹: 我們團隊做的是一個后臺管理系統(tǒng),因為針對不同用戶負責的功能不同那么需要的權(quán)限也就不一樣,所以引入了主流的 shiro 框架做權(quán)限控制,該框架可以控制菜單欄,按鈕,操作框等。在引入這個框架時一并引入了輔助組件shiro-redis,該組件是一個緩存層方便管理用戶登錄信息,內(nèi)存泄漏的問題也是就現(xiàn)在這個輔助組件上。

事件還原: 在周五的中午 11:30 分收到了監(jiān)控的報警信息提示系統(tǒng)在頻繁 Full GC,此時我們立刻做兩件事情: 第一:登錄公司的 UMP 監(jiān)控平臺(開源監(jiān)控可以參考:【Prometheus+grafana 監(jiān)控】)查看該機器的系統(tǒng)指標,發(fā)現(xiàn)確實在頻繁 FullGC 從 11 點持續(xù)到了 11 點半

4fdf7f5e-2d3a-11ee-815d-dac502259ad0.png

第二:保留一臺機器作為證據(jù)收集,其他機器進行重啟保障業(yè)務能正常訪問,重啟后 full gc 正常

第三:堆棧信息操作指令./jmap -F -dump:live,format=b,file=/jmapfile.hprof 18362(-F 操作是強制導出堆棧信息,18362 是應用 pid,通過 top -c 指令獲?。?br />
第四:因為個人無權(quán)限導出堆棧信息,馬上電話聯(lián)系運維通過上面指令導出該機器上的堆棧文件,就是抓取現(xiàn)場證據(jù),因為過了這個時間堆內(nèi)存可能就正常了 根據(jù) JVM 知識分析,常見 Full GC 時的五種情況如下:

1. 老年代內(nèi)存不足(大對象過多或內(nèi)存泄漏)
2. Metaspace 空間不足
3. 代碼主動觸發(fā) System.gc()
4. YGC 時的悲觀策略
5. dump live 的內(nèi)存信息時,比如 jmap -dump:live

分析原因

1、查看公司 SGM 監(jiān)控平臺(開源監(jiān)控可以參考:【Prometheus+grafana 監(jiān)控】),元空間最大內(nèi)存 256M,F(xiàn)ullGC 發(fā)生前后為 117M,排除 Metaspace 不足造成的原因

4fee4c50-2d3a-11ee-815d-dac502259ad0.png

2、在系統(tǒng)中搜索第三方 jar 包,沒有主動執(zhí)行 System.gc () 操作的代碼 3、查看 JVM 啟動參數(shù)中有下面兩個參數(shù),所以排除了 YGC 時候的悲觀策略原因

-XX:CMSInitiatingOccupancyFraction=70      # 堆內(nèi)存達到 70%進行 FullGC
-XX:+UseCMSInitiatingOccupancyOnly         # 禁止 YGC 時的悲觀策略(YGC 前后判斷是否需要 FullGC),只有達到閾值才進行 FullGc

4、通過和運維、研發(fā)組溝通沒有人主動執(zhí)行 dump 操作,查看系統(tǒng)的歷史執(zhí)行指令也沒有 dump 操作,主動 dump 的原因排除 初步分析結(jié)果: 通過上面依靠監(jiān)控平臺、JVM 啟動參數(shù)、代碼排除、指令分析,最終嫌疑最大的就是老年代內(nèi)存空間不足造成頻繁 Full GC,但是作為技術(shù)者,排除法顯然不能作為原因定位的依據(jù),我們還需要繼續(xù)確定我們的猜想,下面會結(jié)合 JVM 啟動參數(shù),Tomcat 啟動參數(shù),堆棧文件三大關鍵要素做具體分析。

下圖是進行 FullGC 時候的老年代內(nèi)存情況,把下面的 72%、1794Mb、2496Mb、448Mb 先記住,下面會跟這些值做對比

5025338c-2d3a-11ee-815d-dac502259ad0.png

指標信息: JVM 核心參數(shù):
-Xms2048M # 系統(tǒng)啟動初始化堆空間
-Xmx4096M # 系統(tǒng)最大堆空間
-Xmn1600M # 年輕代空間(包括 From 區(qū)和 To),F(xiàn)rom 和 To 默認占年輕代 20%
-XX:MaxPermSize=256M # 最大非堆內(nèi)存,按需分配
-XX:MetaspaceSize=256M # 元空間大小,JDK1.8 取消了永久代(PermGen)新增元空間,元空間并不在虛擬機中,而是使用本地內(nèi)存。因此,默認情況下,元空間的大小僅受本地內(nèi)存限制,存儲類和類加載器的元數(shù)據(jù)信息
-XX:CMSInitiatingOccupancyFraction=70 # 堆內(nèi)存達到 70%進行 FullGC
-XX:+UseCMSInitiatingOccupancyOnly # 禁止 YGC 時的悲觀策略(YGC 前后判斷是否需要 FullGC),只有達到閾值才進行 FullGc
-XX:+UseConcMarkSweepGC # 使用 CMS 作為垃圾收集器

Tomcat 核心參數(shù):
maxThreads=750# Tomcat 線程池最多能起的線程數(shù)
minSpareThreads=50# Tomcat 初始化的線程池大小或者說 Tomcat 線程池最少會有這么多線程
acceptCount=1000# Tomcat 維護最大的隊列數(shù)

wKgZomTGGH6AKSiCAAEjU8BCu1s356.jpg

5035b586-2d3a-11ee-815d-dac502259ad0.png

導出堆棧指令:jmap -dump:live,format=b,file=jmapfile.hprof [pid]。導出的文件需要使用 MAT 軟件分析,全稱 MemoryAnalyzer,主要分析堆內(nèi)存。

從堆棧文件分析結(jié)果中發(fā)現(xiàn)有 50 個 org.apache.tomcat.util.threads.TaskThread 占用空間很大。共占用空間 96.16%

50644a22-2d3a-11ee-815d-dac502259ad0.png

每個 TaskThread 實例占用空間 36M 左右

50a6db3a-2d3a-11ee-815d-dac502259ad0.png

查看內(nèi)存詳情保存最大最多的對象是 ThreadLocal 中存儲的 SessionInMemory 對象

511801e8-2d3a-11ee-815d-dac502259ad0.jpg

最終原因: 通過分析上面的 JVM 參數(shù)、Tomcat 參數(shù)、堆棧文件,內(nèi)存泄漏的原因是每個線程中有一個 ThreadLocal 存儲大量 SessionInMemory,因為 Tomcat 的啟動核心線程數(shù)是 50 個,每個線程的內(nèi)存占用 36M 左右,共占用 1.8G,老年代內(nèi)存達到 70% 也就是 2496 * 0.7 = 1747.2M 就會進行垃圾回收,1.8G 剛好比 1747.2M 稍微大一些。但是線程中的對象又沒辦法被回收,所以就會看到系統(tǒng)再頻繁 FullGC。

定位問題

通過上面內(nèi)存分析已經(jīng)定位到內(nèi)存泄漏的原因是每個線程中有大量 SessionInMemory,下面步驟就認真分析代碼找到其中創(chuàng)建如此多對象還不銷毀的原因。

經(jīng)過初步分析發(fā)現(xiàn) SessionInMemory 是引用 shiro-redis 的工具包里面的對象,主要封裝 Session 信息和創(chuàng)建時間。主要作用是在當前線程的 jvm 中做一層緩存當系統(tǒng)頻繁獲取 Session 時不用去 redis 獲取了。SessionInMemary 對象是 shiro 判斷用戶登錄成功時候存儲的數(shù)據(jù),主要包括用戶信息,認證信息,權(quán)限信息等,因為用戶登錄成功后不會重復認證,shiro 會對不同用戶做權(quán)限判斷

分析代碼發(fā)現(xiàn)處理本地緩存 Session 的流程有明顯問題,我畫了一個簡易的流程圖,在介紹流程圖前我先描述一下 Session 和用戶登錄操作如何聯(lián)系起來

我們都知道運營后臺需要用戶登錄,登錄成功后會生成一個 cookie 保存到瀏覽器中,cookie 存儲一個關鍵字段 sessionId 用來標識用戶的狀態(tài)和信息,當用戶訪問頁面調(diào)用接口的時候 shiro 會從請求 Request 中獲取 cookie 中的 sessionId,根據(jù)這個唯一標識生成 Session 來存儲用戶的登錄態(tài)和登錄信息等,這些信息會保存到 redis 中。shiro-redis 組件負責從 redis 中獲取的 Session 信息通過 ThreadLoca 做到線程隔離。

51536b2a-2d3a-11ee-815d-dac502259ad0.png

上圖流程概括就是:用戶訪問頁面先從本地緩存獲取 Session,如果存在且沒有超過一秒就返回結(jié)果,如果沒有 Session 或者過期了就把現(xiàn)在的 Session 刪除并新建一個返回結(jié)果。整體看思路清晰,先獲取 Session,如果沒有就新建返回,如果過期了就刪除再新建返回。

流程圖隱藏的問題(核心問題)

1、多個線程會復制多份相同 Session 使內(nèi)存成倍增加(Session 一樣線程不同) 舉個例子:用戶登錄后臺生成一個 Session,假設請求都到一臺機器上,第一次請求到線程 1,第二個請求到線程 2,因為 Session 一樣但是線程之間是隔離的,所以線程 1 和線程 2 都會創(chuàng)建一份相同 Session 存儲到 ThreaLocal 中,Tomcat 最小空閑線程數(shù)越多復制的 Session 份數(shù)也越多。因為 Tomcat 的核心線程數(shù)不會關閉,所以里面的資源也不會釋放。此處有個疑問 ThreadLocad 的 key 是弱引用但是為什么沒回收呢?下面統(tǒng)統(tǒng)解答

2、舊 Session 無法清除(線程一樣 Session 不同)

舉個例子 1:假設所有請求都到一臺機器的同一個線程,用戶第一次登錄后臺生成 Session1,第一次請求到線程 1,1 秒內(nèi)所有請求都執(zhí)行完了,此時 Session 沒有移除(因為 Session 移除策略是懶刪除,需要等下次同一個 Session 訪問時判斷過期條件再刪除),用戶重新登錄,生成了 Session2,因為 Session2 在線程 1 中還沒有就會重新創(chuàng)建,導致第一次登錄時候用到的 Session1 就一直保存到該線程中了

舉個例子 2:參考例子 1 的思路,如果用戶用 Session1 沒有在 1 秒內(nèi)把所有請求執(zhí)行完,就會執(zhí)行懶刪除操作,但是刪除后又新建了一個,那么用戶重新登錄后剛才新建的那個 Session 還是沒有被刪除,所以總結(jié)出來只要用戶重新登錄必定有一個舊的 Session 會保留到線程中

代碼分析

1、在 RedisSessionDAO.java 文件中定義了一個 ThreadLocal 變量作為線程隔離

51639bd0-2d3a-11ee-815d-dac502259ad0.png

2、用戶訪問接口、js 文件、css 文件等資源的時候會進入 shiro 的攔截機制。在攔截過程中會頻繁調(diào)用 doReasSession () 方法獲取用戶的 Session 信息,主要是獲取信息校驗用戶的權(quán)限控制等。

下面的方法主要整合了獲取 Session 操作和設置 Session 操作,如果從 ThreadLocal 中沒有獲取到或者本地緩存超過 1 秒了就返回 null,判斷為 null 之后就會從 redis 中獲取并新建一個 Session 存儲到 ThreadLoca 中

518fc07a-2d3a-11ee-815d-dac502259ad0.png

3、從 ThreadLocal 中取出 sessionMap,根據(jù) sessionId 在 sessionMap 中尋找 Session,如果沒找到直接返回 null,如果找到了再判斷時間是否超過了 1 秒,如果沒超過返回 Session,如果超過了移除返回 null

51ba5b6e-2d3a-11ee-815d-dac502259ad0.png

4、從 ThreadLocal 中獲取 sessionMap,如果為 null 就新建一個保存起來,因為用戶第一次訪問的時候線程中的 sessionMap 還沒有呢所以要新建。然后向 sessionMap 中存儲 Session 對象

5214b88e-2d3a-11ee-815d-dac502259ad0.png

所以代碼的完成流程總結(jié):獲取 Session 的操作是調(diào)用 getSessionFromThreadLocal () 方法,如果沒有獲取到 Session 就返回 null,調(diào)用 setSessionToThreadLocal () 方法會重新設置一個 Session。如果 Session 在當前線程的保存時間超過 1 秒就 remove。

通過上面分析 JVM、Tomat、堆棧、代碼已經(jīng)把問題定位了,因為 shiro-redis 中存儲的 SessionInMemory 對象處理不當導致線程間存儲越來越多,最終使內(nèi)存泄漏進而導致了頻繁 FullGC。因為我們引用的 shiro-redis 版本是 3.2.2 版本,所以存在這個漏洞,作者已于 2019 年 3 月升級 jar 包到 3.2.3 版本把該問題解決。備注:3.2.2 及以下版本存在該問題

解決問題

解決問題的方案目前有四種。針對我們系統(tǒng)使用的是方案 1 + 方案 4

序號 方案描述 優(yōu)點 缺點
方案 1 每次設置 session 時遍歷刪除以前過期或者為 null 的 session 主動刪除,刪除頻次依賴用戶的訪問頻次 如果在 1 秒內(nèi)有大量用戶訪問,總 session 很多無效 session 很少,遍歷所有 session 做了很多無用功導致訪問變慢
方案 2 取消 threadLocal 策略,所有請求直接查詢緩存(redis) 減少本地內(nèi)存使用 訪問緩存耗時比本地長,經(jīng)過測試發(fā)現(xiàn)一個接口會調(diào)用 16 次左右的獲取 session 操作,一個頁面幾十個接口,直接查詢緩存性能存在問題
方案 3 使用本地緩存(guavaCache 或者 EhCache 等),并對緩存做移除策略 多個線程共用一份內(nèi)存,節(jié)省內(nèi)存空間,提升系統(tǒng)性能 對框架有深入了解,接入需要開發(fā)成本
方案 4 把 tomcat 的核心線程數(shù)減小,比如把原來的 50 改成 5 減少系統(tǒng)資源,減少相同 Session 的復制份數(shù),大于 5 的線程銷毀資源也一起回收 處理并發(fā)能力略低

疑問解答

Q:在 RedisSessionDAO 里面只定義了一個 ThreadLocal 的變量 sessionsInThread,怎么就會是 50 個線程把相同的 Session 復制 50 份呢?

A:首先我們先理解 ThreadLocal 的結(jié)構(gòu),ThreadLocal 有一個靜態(tài)類 ThreadLocalMap,ThreadLocalMap 里面還有一個 Entry,我們的 key 和 value 就是保存在 Entry 的,key 是一個弱引用的 ThreadLocal 類型,,這個 key 在所有的線程中都是一樣的,實際上就是我們定義的靜態(tài) sessionsInThread。那又是怎么做到線程隔離的呢?

這就講到 Thread 中的一個成員變量 threadLocals,這個對象就是 ThreadLocal.ThreadLocalMap 類型,也就是每次創(chuàng)建一個線程都會 new 一個 ThreadLocalMap,所以每個線程中的 ThreadLocalMap 都是不同的,但是里面 Entry 存儲的 key 都是一樣的,也就是我們前面定義的 sessionsInThread 靜態(tài)變量。

當一個線程需要獲取 Entry 中存儲的 value 時候,調(diào)用 sessionsInThread.get () 方法,這個方法做了三件事情,一是獲取當前線程的實例,二是從線程實例中獲取 ThreadLocalMap,三是從 ThreadLocalMap 中根據(jù) ThreadLocal 這個 key 獲取指定的 value

52453d7e-2d3a-11ee-815d-dac502259ad0.png

獲取 Thread 中的 ThreadLocalMap

525fe52a-2d3a-11ee-815d-dac502259ad0.png

從 ThreadLocalMap 中獲取指定的 value,又有個疑問,獲取 Entry 為什么還要從一個 table 數(shù)組中拿呢?這個很好理解一個線程不一定只有一個 ThreadLocal 變量吧,多個 ThreadLocal 變量就是有多個 key,所以就放到 table 數(shù)組里面了

527baf26-2d3a-11ee-815d-dac502259ad0.png

Q:都說 ThreadLocal 的 key 是一個弱引用,如果內(nèi)存不足了會被垃圾回收,咱們的 key 從堆??床]有回收呀?

A:這是個好問題,首先我們的 RedisSessionDAO 是 Spring 注入的單例模式,ThreadLocal 被定義成一個靜態(tài)變量,靜態(tài)變量在內(nèi)存中是不會回收的。

補充:一般我們在使用 ThreadLocal 的時候都會定義成靜態(tài)變量,如果定義成非靜態(tài)變量創(chuàng)建一個對象就會 new 一個 ThreadLocal,那么 ThreadLocal 就沒有存在的意義了。

Q:已經(jīng)結(jié)束的線程,為什么還會存活,里面的對象也不會消失?

A:因為設置的最小空閑線程數(shù)是 50,業(yè)務量不大并發(fā)數(shù)沒有超過 50,tomcat 會保留最小的線程數(shù)量不會新建也不用回收,ThreadLocalMap 是線程中的成員變量所以不會回收

Q:訪問一次接口就會生成一個 sessionId 嗎?

A:訪問接口先判斷用戶信息是否有效,無效才會重新登錄獲取新的 sessionId

Q:shiro-redis 在本地保存 Session 為什么設置 1 秒過期時間?

A:因為運營后臺不同于業(yè)務接口會持續(xù)調(diào)用,后臺接口大部分的場景是用戶訪問一個頁面并停留在頁面上做一些操作,訪問一個頁面的時候瀏覽器會加載多個資源,包括靜態(tài)資源 html,css,js 等,和接口的動態(tài)數(shù)據(jù),整個資源加載過程盡量保持在一秒內(nèi)完成,如果超過一秒的話系統(tǒng)體驗性能較差,所以本地緩存一秒足夠了。

收獲總結(jié)

報警前:

1. 熟悉第三方 jar 包的工作原理,尤其是個人開發(fā)工具包,因為沒有經(jīng)過市場檢驗使用前要格外小心

2. 可以使用 jvisualvm 進行本地壓測觀察 jvm 情況

3. 關注監(jiān)控報警,掌握監(jiān)控平臺操作,能夠從監(jiān)控中查詢系統(tǒng)各項指標信息

4. 根據(jù)業(yè)務合理配置 JVM 參數(shù)和 Tomcat 參數(shù)

報警后:

1. 能夠第一時間抓取系統(tǒng)的 JVM 信息,比如堆棧,GC 信息,線程棧等

2. 通過使用 MAT 內(nèi)存輔助軟件幫助自己分析問題原因






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 存儲器
    +關注

    關注

    39

    文章

    7698

    瀏覽量

    170339
  • JAVA語言
    +關注

    關注

    0

    文章

    138

    瀏覽量

    21025
  • cms
    cms
    +關注

    關注

    0

    文章

    60

    瀏覽量

    11390
  • 緩存器
    +關注

    關注

    0

    文章

    63

    瀏覽量

    11993
  • JVM
    JVM
    +關注

    關注

    0

    文章

    160

    瀏覽量

    12904

原文標題:頻繁FullGC的原因竟然是 “開源代碼”?

文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    N9H20 GPIO上電竟然是高電平,有沒有辦法解決?

    一直很納悶,GPIO上電竟然是高電平。有沒有辦法解決,是不是要改動啟動程序才能解決問題?
    發(fā)表于 01-17 08:27

    基于OMPL的運動規(guī)劃介紹與教程_ROS_開源代碼1 #開源代碼

    機器人開源硬件源代碼代碼控制算法開源代碼
    薪盡火傳
    發(fā)布于 :2022年08月24日 16:28:03

    基于OMPL的運動規(guī)劃介紹與教程_ROS_開源代碼 2#開源代碼

    機器人開源硬件源代碼代碼控制算法開源代碼
    薪盡火傳
    發(fā)布于 :2022年08月24日 16:28:41

    基于OMPL的運動規(guī)劃介紹與教程_ROS_開源代碼3 #開源代碼

    機器人開源硬件源代碼代碼控制算法開源代碼
    薪盡火傳
    發(fā)布于 :2022年08月24日 16:29:46

    基于OMPL的運動規(guī)劃介紹與教程_ROS_開源代碼4 #開源代碼

    機器人開源硬件源代碼代碼控制算法開源代碼
    薪盡火傳
    發(fā)布于 :2022年08月24日 16:29:51

    [轉(zhuǎn)帖]這樣的建站程序,竟然是免費的!

    這樣的建站程序,竟然是免費的!廢話就不多說了,大家看了圖再發(fā)表意見吧![/url][url=http://b86.net]這樣的程序,只需要,購買耐思尼克www.b86.net/?s=cartoon
    發(fā)表于 05-22 16:06

    SRTP,被刷下來了,原因竟然是抽簽被抽到

    本帖最后由 iiio051031448 于 2012-4-1 12:36 編輯 SRTP,被刷下來了,如果是項目不合理,或者沒有別人的好,我也就認了,自己能力不行。原因竟然是抽簽被抽到,就你不行我還能相信學校么?!
    發(fā)表于 04-01 01:00

    影響PCB價格的因素竟然是這些,表示都忽略了

    影響PCB價格的因素竟然是這些,表示都忽略了
    發(fā)表于 04-09 19:41

    Arduino 的開源代碼 在哪找

    各位哥哥姐姐,姐夫大嫂,有誰能告訴我 Arduino 的開源代碼 在哪找 ?小弟不勝感激!!
    發(fā)表于 08-25 13:52

    電磁爐干燒的原因竟然是最不起眼的小元件!

    `電磁爐干燒的原因竟然是不起眼的小元件你知道嗎隨著科技的發(fā)展,電磁爐使用頻率越來頻繁,加熱,炒菜,等等…大部分食材都會用到電磁爐,現(xiàn)如今電磁爐都有一套保護系統(tǒng),可是還是會出現(xiàn)干燒,不加熱故障
    發(fā)表于 07-20 09:59

    四軸開源代碼IAR

    四軸飛行器開源 源代碼IAR需要的自行下載吧。
    發(fā)表于 03-31 15:26 ?5次下載

    蘋果系統(tǒng)泄密 來自iOS源代碼

    iPhone源碼泄漏,iOS也涼了?這個最嚴重的泄密竟然是來自 iOS 源代碼。當時其實他們只是在專門整代碼分享的網(wǎng)站 GitHub 上發(fā)現(xiàn),這竟然是 iPhone 的操作系統(tǒng)的核心組
    的頭像 發(fā)表于 02-11 10:50 ?6121次閱讀

    MWC四軸開源代碼免費下載

    本文檔的主要內(nèi)容詳細介紹的是MWC四軸開源代碼免費下載。
    發(fā)表于 03-31 08:00 ?20次下載

    你不知道的FPC,它的發(fā)展史竟然是這樣的!

    你不知道的FPC,它的發(fā)展史竟然是這樣的!
    的頭像 發(fā)表于 11-15 10:48 ?2129次閱讀

    UPS(不間斷電源)故障頻發(fā)?原因竟然是這樣

    UPS(不間斷電源)故障頻發(fā)?原因竟然是這樣
    的頭像 發(fā)表于 04-19 13:53 ?1076次閱讀
    UPS(不間斷電源)故障頻發(fā)?<b class='flag-5'>原因</b><b class='flag-5'>竟然是</b>這樣