雲原生時代,Java的危與機

2020-12-08 InfoQ技術實驗室

Java誕生距今已有25年,但它仍然長期佔據著「天下第一」程式語言的寶座。只是其統治地位並非堅不可摧,反倒可以說是危機四伏。雲原生時代,Java技術體系的許多前提假設都受到了挑戰,目前已經有可預見的、足以威脅動搖其根基的潛在可能性正在醞釀。同時,像Golang、Rust這樣的新生語言,以及C、C++、C#、Python等老對手也都對Java的市場份額虎視眈眈。面對危機,Java正在嘗試哪些變革?未來,Java是會繼續向前、再攀高峰,還是由盛轉衰?在今天由極客邦科技舉辦的QCon全球軟體開發大會2020(深圳站)上,遠光軟體研究院院長、《深入理解Java虛擬機》系列書籍作者周志明發表了主題演講《雲原生時代的Java》,以下內容為演講整理。

今天,25 歲的 Java 仍然是最具有統治力的程式語言,長期佔據程式語言排行榜的首位,擁有一千二百萬的龐大開發者群體,全世界有四百五十億部物理設備使用著 Java 技術,同時,在雲端數據中心的虛擬化環境裡,還運行著超過兩百五十億個 Java 虛擬機的進程實例 (數據來自Oracle的WebCast)。

以上這些數據是 Java 過去 25 年巨大成就的功勳佐證,更是 Java 技術體系維持自己「天下第一」程式語言的堅實壁壘。Java 與其他語言競爭,底氣從來不在於語法、類庫有多麼先進好用,而是來自它龐大的用戶群和極其成熟的軟體生態,這在朝夕之間難以撼動。然而,這個現在看起來仍然堅不可摧的 Java 帝國,其統治地位的穩固程度不僅沒有高枕無憂,反而說是危機四伏也不為過。目前已經有了可預見的、足以威脅動搖其根基的潛在可能性正在醞釀,並隨雲原生時代而降臨。

Java 的危機

Java 與雲原生的矛盾,來源於 Java 誕生之初,植入到它基因之中的一些基本的前提假設已經逐漸開始被動搖,甚至已經不再成立。

我舉個例子,每一位 Java 的使用者都聽說過「一次編寫,到處運行」(Write Once, Run Anywhere)這句口號。20 多年前,Java 成熟之前,開發者如果希望程序在 Linux、Solaris、Windows 等不同平臺,在 x86、AMD64、SPARC、MIPS、ARM 等不同指令集架構上都能正常運行,就必須針對每種組合,編譯出對應的二進位發行包,或者索性直接分發原始碼,由使用者在自己的平臺上編譯。

面對這個問題,Java 通過語言層虛擬化的方式,令每一個 Java 應用都自動取得平臺無關(Platform Independent)、架構中立(Architecture Neutral)的先天優勢,讓同一套程序格式得以在不同指令集架構、不同作業系統環境下都能運行且得到一致的結果,不僅方便了程序的分發,還避免了各種平臺下內存模型、線程模型、字節序等底層細節差異對程序編寫的幹擾。在當年,Java 的這種設計帶有令人趨之若鶩的強大吸引力,直接開啟了託管語言(Managed Language,如 Java、.NET)的一段興盛期。

面對相同的問題,今天的雲原生選擇以作業系統層虛擬化的方式,通過容器實現的不可變基礎設施去解決。不可變基礎設施這個概念出現得比雲原生要早,原本是指該如何避免由於運維人員對伺服器運行環境所做的持續的變更而導致的意想不到的副作用。但在雲原生時代,它的內涵已不再局限於方便運維、程序升級和部署的手段,而是升華一種為向應用代碼隱藏環境複雜性的手段,是分布式服務得以成為一種可普遍推廣的普適架構風格的必要前提。

將程序連同它的運行環境一起封裝到穩定的鏡像裡,現已是一種主流的應用程式分發方式。Docker 同樣提出過「一次構建,到處運行」(Build Once, Run Anywhere)的口號,儘管它只能提供環境兼容性和有局限的平臺無關性(指系統內核功能以上的 ABI 兼容),且完全不可能支撐架構中立性,所以將「一次構建,到處運行」與「一次編寫,到處運行」對立起來並不嚴謹恰當,但是無可否認,今天 Java 技術「一次編譯,到處運行」的優勢,已經被容器大幅度地削弱,不再是大多數服務端開發者技術選型的主要考慮因素了。

如果僅僅是優勢的削弱,並不足以成為 Java 的直接威脅,充其量只是一個潛在的不利因素,但更加迫在眉睫的風險來自於那些與技術潮流直接衝突的假設。譬如,Java 總體上是面向大規模、長時間的服務端應用而設計的,嚴(luō)謹(suō)的語法利於約束所有人寫出較一致的代碼;靜態類型動態連結的語言結構,利於多人協作開發,讓軟體觸及更大規模;即時編譯器、性能制導優化、垃圾收集子系統等 Java 最具代表性的技術特徵,都是為了便於長時間運行的程序能享受到硬體規模發展的紅利。

另一方面,在微服務的背景下,提倡服務圍繞業務能力而非技術來構建應用,不再追求實現上的一致,一個系統由不同語言,不同技術框架所實現的服務來組成是完全合理的;服務化拆分後,很可能單個微服務不再需要再面對數十、數百 GB 乃至 TB 的內存;有了高可用的服務集群,也無須追求單個服務要 7×24 小時不可間斷地運行,它們隨時可以中斷和更新。

同時,微服務又對應用的容器化親和性,譬如鏡像體積、內存消耗、啟動速度,以及達到最高性能的時間等方面提出了新的要求。這兩年的網紅概念 Serverless 也進一步增加這些因素的考慮權重,而這些卻正好都是 Java 的弱項:哪怕再小的 Java 程序也要帶著完整的虛擬機和標準類庫,使得鏡像拉取和容器創建效率降低,進而使整個容器生命周期拉長。基於 Java 虛擬機的執行機制,使得任何 Java 的程序都會有固定的基礎內存開銷,以及固定的啟動時間,而且 Java 生態中廣泛採用的依賴注入進一步將啟動時間拉長,使得容器的冷啟動時間很難縮短。

軟體工業中已經出現過不止一起因 Java 這些弱點而導致失敗的案例,如 JRuby 編寫的Logstash,原本是同時承擔部署在節點上的收集端(Shipper)和專門轉換處理的服務端(Master)的職責,後來因為資源佔用的原因,被Elstaic.co用 Golang 的Filebeat代替了 Shipper 部分的職能;又如 Scala 語言編寫的邊車代理Linkerd,作為服務網格概念的提出者,卻最終被Envoy所取代,其主要弱點之一也是由於 Java 虛擬機的資源消耗所帶來的劣勢。

雖然在雲原生時代依然有很多適合 Java 發揮的領域,但是具備彈性與韌性、隨時可以中斷重啟的微型服務的確已經形成了一股潮流,在逐步蠶食大型系統的領地。正是由於潮流趨勢的改變,新一代的語言與技術尤其重視輕量化和快速響應能力,大多又重新回歸到了原生語言(Native Language,如 Golang、Rust)之上。

Java 的變革

面對挑戰,Java 的開發者和社區都沒有退縮,它們在各自的領域給出了很多優秀的解決方案,湧現了如Quarkus、Micronaut、Helidon等一大批以提升 Java 在雲原生環境下的適應性為賣點的框架。

不過,今天我們的主題將聚焦在由 Java 官方本身所推進的項目上。在圍繞 Java 25 周年的研討和布道活動中,官方的設定是以「面向未來的變革」(Innovating for the Future)為基調,你有可能在此之前已經聽說過其中某個(某些)項目的名字和改進點,但這裡我們不僅關心這些項目改進的是什麼,還更關心它們背後的動機與困難、帶來的收益,以及要付出的代價。

Innovating for the Future

Project Leyden

對於原生語言的挑戰,最有力最徹底的反擊手段無疑是將字節碼直接編譯成可以脫離 Java 虛擬機的原生代碼。如果真的能夠生成脫離 Java 虛擬機運行的原生程序,將意味著啟動時間長的問題能夠徹底解決,因為此時已經不存在初始化虛擬機和類加載的過程;也意味著程序馬上就能達到最佳的性能,因為此時已經不存在即時編譯器運行時編譯,所有代碼都是在編譯期編譯和優化好的(如下圖所示);沒有了 Java 虛擬機、即時編譯器這些額外的部件,也就意味著能夠省去它們原本消耗的那部分內存資源與鏡像體積。

Java Performance Matrices(圖片來源)

但同時,這也是風險係數最高、實現難度最大的方案。

Java 並非沒有嘗試走過這條路,從 Java 2 之前的GCJ(GNU Compiler for Java),到後來的Excelsior JET,再到 2018 年 Oracle Labs 啟動的GraalVM中的SubstrateVM模塊,最後到 2020 年中期剛建立的Leyden項目,都在朝著提前編譯(Ahead-of-Time Compilation,AOT)生成原生程序這個目標邁進。

Java 支持提前編譯最大的困難在於它是一門動態連結的語言,它假設程序的代碼空間是開放的(Open World),允許在程序的任何時候通過類加載器去加載新的類,作為程序的一部分運行。要進行提前編譯,就必須放棄這部分動態性,假設程序的代碼空間是封閉的(Closed World),所有要運行的代碼都必須在編譯期全部可知。這一點不僅僅影響到了類加載器的正常運作,除了無法再動態加載外,反射(通過反射可以調用在編譯期不可知的方法)、動態代理、字節碼生成庫(如 CGLib)等一切會運行時產生新代碼的功能都不再可用,如果將這些基礎能力直接抽離掉,Helloworld 還是能跑起來,但 Spring 肯定跑不起來,Hibernate 也跑不起來,大部分的生產力工具都跑不起來,整個 Java 生態中絕大多數上層建築都會轟然崩塌。

要獲得有實用價值的提前編譯能力,只有依靠提前編譯器、組件類庫和開發者三方一起協同才可能辦到。由於 Leyden 剛剛開始,幾乎沒有公開的資料,所以下面我是以 SubstrateVM 為目標對象進行的介紹:

有一些功能,像反射這樣的基礎特性是不可能妥協的,折衷的解決辦法是由用戶在編譯期,以配置文件或者編譯器參數的形式,明確告知編譯器程序代碼中有哪些方法是只通過反射來訪問的,編譯器將方法的添加到靜態編譯的範疇之中。同理,所有使用到動態代理的地方,也必須在事先列明,在編譯期就將動態代理的字節碼全部生成出來。其他所有無法通過程序指針分析(Points-To Analysis)得到的信息,譬如程序中用到的資源、配置文件等等,也必須照此處理。另一些功能,如動態生成字節碼也十分常用,但用戶自己往往無法得知那些動態字節碼的具體信息,就只能由用到CGLib、javassist等庫的程序去妥協放棄。在Java世界中也許最典型的場景就是Spring用CGLib來進行類增強,默認情況下,每一個Spring管理的Bean都要用到CGLib。從Spring Framework 5.2開始增加了@proxyBeanMethods註解來排除對CGLib的依賴,僅使用標準的動態代理去增強類。2019 年起,Pivotal 的 Spring 團隊與 Oracle Labs 的 GraalVM 團隊共同孵化了 Spring GraalVM Native 項目,這個目前仍處於 Experimental / Alpha 狀態的項目,能夠讓程序先以傳統方式運行(啟動)一次,自動化地找出程序中的反射、動態代理的代碼,代替用戶向編譯器提供絕大部分所需的信息,並能將允許啟動時初始化的 Bean 在編譯期就完成初始化,直接繞過 Spring 程序啟動最慢的階段。這樣從啟動到程序可以提供服務,耗時竟能夠低於 0.1 秒。

Spring Boot Startup Time(數據來源)

以原生方式運行後,縮短啟動時間的效果立竿見影,一般會有數十倍甚至更高的改善,程序容量和內存消耗也有一定程度的下降。不過至少目前而言,程序的運行效率還是要弱於傳統基於 Java 虛擬機的方式,雖然即時編譯器有編譯時間的壓力,但由於可以進行基於假設的激進優化和運行時性能度量的制導優化,使得即時編譯器的效果仍要優於提前編譯器,這方面需要 GraalVM 編譯器團隊的進一步努力,也需要從語言改進上入手,讓 Java 變得更適合被編譯器優化。

Project Valhalla

Java 語言上可感知的語法變化,多數來自於Amber項目,它的項目目標是持續優化語言生產力,近期(JDK 15、16)會有很多來自這個項目的特性,如 Records、Sealed Class、Pattern Matching、Raw String Literals 等實裝到生產環境。

然而語法不僅與編碼效率相關,與運行效率也有很大關係。「程序=代碼+數據」這個提法至少在衡量運行效率上是合適的,無論是託管語言還是原生語言,最終產物都是處理器執行的指令流和內存存儲的數據結構。Java、.NET、C、C++、Golang、Rust 等各種語言誰更快,取決於特定場景下,編譯器生成指令流的優化效果,以及數據在內存中的結構布局。

Java 即時編譯器的優化效果拔群,但是由於 Java「一切皆為對象」的前提假設,導致在處理一系列不同類型的小對象時,內存訪問性能非常拉垮,這點是 Java 在遊戲、圖形處理等領域一直難有建樹的重要制約因素,也是 Java 建立Valhalla項目的目標初衷。

這裡舉個例子來說明此問題,如果我想描述空間裡面若干條線段的集合,在 Java 中定義的代碼會是這樣的:

public record Point(float x, float y, float z) {}public record Line(Point start, Point end) {}Line[] lines;面向對象的內存布局中,對象標識符(Object Identity)存在的目的是為了允許在不暴露對象結構的前提下,依然可以引用其屬性與行為,這是面向對象編程中多態性的基礎。在 Java 中堆內存分配和回收、空值判斷、引用比較、同步鎖等一系列功能都會涉及到對象標識符,內存訪問也是依靠對象標識符來進行鏈式處理的,譬如上面代碼中的「若干條線段的集合」,在堆內存中將構成如下圖的引用關係:

Object Identity / Memory Layout

計算機硬體經過 25 年的發展,內存與處理器雖然都在進步,但是內存延遲與處理器執行性能之間的馮諾依曼瓶頸(Von Neumann Bottleneck)不僅沒有縮減,反而還在持續加大,「RAM Is the New Disk」已經從嘲諷梗逐漸成為了現實。

一次內存訪問(將主內存數據調入處理器 Cache)大約需要耗費數百個時鐘周期,而大部分簡單指令的執行只需要一個時鐘周期而已。因此,在程序執行性能這個問題上,如果編譯器能減少一次內存訪問,可能比優化掉幾十、幾百條其他指令都來得更有效果。

額外知識:馮諾依曼瓶頸不同處理器(現代處理器都集成了內存管理器,以前是在北橋晶片中)的內存延遲大概是40-80納秒(ns,十億分之一秒),而根據不同的時鐘頻率,一個時鐘周期大概在0.2-0.4納秒之間,如此短暫的時間內,即使真空中傳播的光,也僅僅能夠行進10釐米左右。數據存儲與處理器執行的速度矛盾是馮諾依曼架構的主要局限性之一,1977年的圖靈獎得主John Backus提出了「馮諾依曼瓶頸」這個概念,專門用來描述這種局限性。

編譯器的確在努力減少內存訪問,從 JDK 6 起,HotSpot 的即時編譯器就嘗試通過逃逸分析來做標量替換(Scalar Replacement)和棧上分配(Stack Allocations)優化,基本原理是如果能通過分析,得知一個對象不會傳遞到方法之外,那就不需要真實地在對中創建完整的對象布局,完全可以繞過對象標識符,將它拆散為基本的原生數據類型來創建,甚至是直接在棧內存中分配空間(HotSpot 並沒有這樣做),方法執行完畢後隨著棧幀一起銷毀掉。

不過,逃逸分析是一種過程間優化(Interprocedural Optimization),非常耗時,也很難處理那些理論有可能但實際不存在的情況。相同的問題在 C、C++中卻並不存在,上面場景中,程式設計師只要將 Point 和 Line 都定義為 struct 即可,C#中也有 struct,是依靠.NET 的值類型(Value Type)來實現的。Valhalla 項目的核心改進就是提供類似的值類型支持,提供一個新的關鍵字(inline),讓用戶可以在不需要向方法外部暴露對象、不需要多態性支持、不需要將對象用作同步鎖的場合中,將類標識為值類型,此時編譯器就能夠繞過對象標識符,以平坦的、緊湊的方式去為對象分配內存。

有了值類型的支持後,現在 Java 泛型中令人詬病的不支持原數據類型(Primitive Type)、頻繁裝箱問題也就隨之迎刃而解,現在 Java 的包裝類,理所當然地會以代表原生類型的值類型來重新定義,這樣 Java 泛型的性能會得到明顯的提升,因為此時 Integer 與 int 的訪問,在機器層面看完全可以達到一致的效率。

Project Loom

Java 語言抽象出來隱藏了各種作業系統線程差異性的統一線程接口,這曾經是它區別於其他程式語言(C/C++表示有被冒犯到)的一大優勢,不過,統一的線程模型不見得永遠都是正確的

Java 目前主流的線程模型是直接映射到作業系統內核上的1:1模型,這對於計算密集型任務這很合適,既不用自己去做調度,也利於一條線程跑滿整個處理器核心。但對於 I/O 密集型任務,譬如訪問磁碟、訪問資料庫佔主要時間的任務,這種模型就顯得成本高昂,主要在於內存消耗和上下文切換上:64 位 Linux 上 HotSpot 的線程棧容量默認是 1MB,線程的內核元數據(Kernel Metadata)還要額外消耗 2-16KB 內存,所以單個虛擬機的最大線程數量一般只會設置到 200 至 400 條,當程式設計師把數以百萬計的請求往線程池裡面灌時,系統即便能處理得過來,其中的切換損耗也相當可觀。

Loom 項目的目標是讓 Java 支持額外的N:M線程模型,請注意是「額外支持」,而不是像當年從綠色線程過渡到內核線程那樣的直接替換,也不是像 Solaris 平臺的 HotSpot 虛擬機那樣通過參數讓用戶二選其一。

Loom 項目新增加一種「虛擬線程」(Virtual Thread,以前以 Fiber 為名進行宣傳過,但因為要頻繁解釋啥是 Fiber 所以現在放棄了),本質上它是一種有棧協程(Stackful Coroutine),多條虛擬線程可以映射到同一條物理線程之中,在用戶空間中自行調度,每條虛擬線程的棧容量也可由用戶自行決定。

Virtual Thread

同時,Loom 項目的另一個目標是要盡最大可能保持原有統一線程模型的交互方式,通俗地說就是原有的 Thread、J.U.C、NIO、Executor、Future、ForkJoinPool 等這些多線程工具都應該能以同樣的方式支持新的虛擬線程,原來多線程中你理解的概念、編碼習慣大多數都能夠繼續沿用。

為此,虛擬線程將會與物理線程一樣使用java.lang.Thread來進行抽象,只是在創建線程時用到的參數或者方法稍有不同(譬如給 Thread 增加一個Thread.VIRTUAL_THREAD參數,或者增加一個startVirtualThread()方法)。這樣現有的多線程代碼遷移到虛擬線程中的成本就會變得很低,而代價就是 Loom 的團隊必須做更多的工作以保證虛擬線程在大部分涉及到多線程的標準 API 中都能夠兼容,甚至在調試器上虛擬線程與物理線程看起來都會有一致的外觀。但很難全部都支持,譬如調用 JNI 的本地棧幀就很難放到虛擬線程上,所以一旦遇到本地方法,虛擬線程就會被綁定(Pinned)到一條物理線程上。

Loom 的另一個重點改進是支持結構化並發(Structured Concurrency),這是 2016 年才提出的新的並發編程概念,但很快就被諸多程式語言所吸納。它是指程序的並發行為會與代碼的結構對齊,譬如以下代碼所示,按照傳統的編程觀念,如果沒有額外的處理(譬如無中生有地弄一個 await 關鍵字),那在task1和task2提交之後,程序應該繼續向下執行:

ThreadFactory factory = Thread.builder().virtual().factory();try (var executor = Executors.newThreadExecutor(factory)) { executor.submit(task1); executor.submit(task2);} // blocks and waits但是在結構化並發的支持下,只有兩個並行啟動的任務線程都結束之後,程序才會繼續向下執行,很好地以同步的編碼風格,來解決異步的執行問題。事實上,「Code like sync,Work like async」正是 Loom 簡化並發編程的核心理念。

Project Portola

Portola 項目的目標是將 OpenJDK 向 Alpine Linux 移植。Alpine Linux 是許多 Docker 容器首選的基礎鏡像,因為它只有 5 MB 大小,比起其他 Cent OS、Debain 等動輒一百多 MB 的發行版來說,更適合用於容器環境。不過 Alpine Linux 為了儘量瘦身,默認是用musl作為 C 標準庫的,而非傳統的glibc(GNU C library),因此要以 Alpine Linux 為基礎製作 OpenJDK 鏡像,必須先安裝 glibc,此時基礎鏡像大約有 12 MB。Portola 計劃將 OpenJDK 的上遊代碼移植到 musl,並通過兼容性測試。使用 Portola 製作的標準 Java SE 13 鏡像僅有 41 MB,不僅遠低於 Cent OS 的 OpenJDK(大約 396 MB),也要比官方的 slim 版(約 200 MB)要小得多。

$ sudo docker build .Sending build context to Docker daemon 2.56kBStep 1/8 : FROM alpine:latest as buildlatest: Pulling from library/alpinebdf0201b3a05: Pull completeDigest: sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913Status: Downloaded newer image for alpine:latest ---> cdf98d1859c1Step 2/8 : ADD https://download.java.net/java/early_access/alpine/16/binaries/openjdk-13-ea+16_linux-x64-musl_bin.tar.gz /opt/jdk/Downloading [==================================================>] 195.2MB/195.2MB ---> Using cache ---> b1a444e9dde9Step 3/7 : RUN tar -xzvf /opt/jdk/openjdk-13-ea+16_linux-x64-musl_bin.tar.gz -C /opt/jdk/ ---> Using cache ---> ce2721c75ea0Step 4/7 : RUN ["/opt/jdk/jdk-13/bin/jlink", "--compress=2", "--module-path", "/opt/jdk/jdk-13/jmods/", "--add-modules", "java.base", "--output", "/jlinked"] ---> Using cache ---> d7b2793ed509Step 5/7 : FROM alpine:latest ---> cdf98d1859c1Step 6/7 : COPY --from=build /jlinked /opt/jdk/ ---> Using cache ---> 993fb106f2c2Step 7/7 : CMD ["/opt/jdk/bin/java", "--version"] - to check JDK version ---> Running in 8e1658f5f84dRemoving intermediate container 8e1658f5f84d ---> 350dd3a72a7dSuccessfully built 350dd3a72a7d$ sudo docker tag 350dd3a72a7d jdk-13-musl/jdk-version:v1$ sudo docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEjdk-13-musl/jdk-version v1 350dd3a72a7d About a minute ago 41.7MBalpine latest cdf98d1859c1 2 weeks ago 5.53MJava 的未來

雲原生時代,Java 技術體系的許多前提假設都受到了挑戰,「一次編譯,到處運行」、「面向長時間大規模程序而設計」、「從開放的代碼空間中動態加載」、「一切皆為對象」、「統一線程模型」,等等。技術發展迭代不會停歇,沒有必要堅持什麼「永恆的真理」,舊的原則被打破,只要合理,便是創新。

Java 語言意識到了挑戰,也意識到了要面向未來而變革。文中提到的這些項目,Amber 和 Portola 已經明確會在 2021 年 3 月的 Java 16 中發布,至少也會達到 Feature Preview 的程度:

JEP 394:Pattern Matching for instanceofJEP 395:RecordsJEP 397:Sealed ClassesJEP 386:Alpine Linux Port至於更受關注,同時也是難度更高的 Valhalla 和 Loom 項目,目前仍然沒有明確的版本計劃信息,儘管它們已經開發了數年時間,非常希望能夠趕在 Java 17 這個 LTS 版本中面世,但前路還是困難重重。

至於難度最高、創建時間最晚的 Leyden 項目,目前還完全處於特性討論階段,連個胚胎都算不上。對於 Java 的原生編譯,我們中短期內只可能寄希望於 Oracle 的 GraalVM。

未來一段時間,是 Java 重要的轉型窗口期,如果作為下一個 LTS 版的 Java 17,能夠成功集 Amber、Portola、Valhalla、Loom 和 Panama(用於外部函數接口訪問,本文沒有提到)的新能力、新特性於一身,GraalVM 也能給予足夠強力支持的話,那 Java 17 LTS 大概率會是一個裡程碑式的版本,帶領著整個 Java 生態從大規模服務端應用,向新的雲原生時代軟體系統轉型。可能成為比肩當年從面向嵌入式設備與瀏覽器 Web Applets 的 Java 1,到確立現代 Java 語言方向(Java SE/EE/ME 和 JavaCard)雛形的 Java 2 轉型那樣的裡程碑。

但是,如果 Java 不能加速自己的發展步伐,那由強大生態所構建的護城河終究會消耗殆盡,被 Golang、Rust 這樣的新生語言,以及 C、C++、C#、Python 等老對手蠶食掉很大一部分市場份額,以至被迫從「天下第一」程式語言的寶座中退位。

Java 的未來是繼續向前,再攀高峰,還是由盛轉衰,鋒芒挫縮,你我拭目以待。

會議推薦:

歡迎繼續關註明天 QCon 深圳的精彩分享。QCon 上海和北京站也將在之後給大家帶來更多網際網路大廠的技術解讀和案例推薦。12 月 20-21 日QCon全球軟體開發大會(上海站)設置業務架構演進、研發效能提升、微服務、智能金融、5G+新基建、高可用、雲原生開發基礎架構等熱門技術專題,邀請近 80 位網際網路大咖與會分享,捱過難熬的 2020,我們還你幾場技術盛會!

延伸閱讀:

66歲還在寫代碼,這個程式設計師想把bug扼殺在「搖籃」裡-InfoQ

關注我並轉發此篇文章,私信我「領取資料」,即可免費獲得InfoQ價值4999元迷你書,點擊文末「了解更多」,即可移步InfoQ官網,獲取最新資訊~

相關焦點

  • 雲原生時代,Java危矣?
    雲原生時代,Java 技術體系的許多前提假設都受到了挑戰,目前已經有可預見的、足以威脅動搖其根基的潛在可能性正在醞釀。同時,像 Golang、Rust 這樣的新生語言,以及 C、C++、C#、Python 等老對手也都對 Java 的市場份額虎視眈眈。面對危機,Java 正在嘗試哪些變革?未來,Java 是會繼續向前、再攀高峰,還是由盛轉衰?
  • KubeSphere容器平臺:面向雲原生時代的趁手工具
    在所有企業都在加快數位化步伐,邁入雲原生時代的當下,青雲推出一款面向社區的「劃時代產品」,這樣做的路徑是怎樣的呢?雲原生時代的基礎設施如果要理解KubeSphere是怎樣的一款產品,那麼首先要理解雲原生時代對於企業的必然性。
  • 雲原生時代的流量入口:Envoy Gateway
    當雲原生時代大浪襲來,Envoy 這一 CNCF 畢業數據面組件為更多人所知。那麼,優秀「畢業生」Envoy 能否成為雲原生時代下流量入口標準組件?背景 —— 流量入口的眾多選型與場景在網際網路體系下,凡是需要對外暴露的系統幾乎都需要網絡代理:較早出現的 HAProxy、Nginx 至今仍在流行;進入微服務時代後,功能更豐富、管控能力更強的 API 網關又成為流量入口必備組件;在進入容器時代後,Kubernetes Ingress 作為容器集群的入口,是容器時代微服務的流量入口代理標準。
  • 華為雲原生精英沙龍圓滿落幕,行業翹楚論道雲原生
    從2015年到2020年,企業IT數位化戰略從「Cloud First」演進到「Cloud Native First」,「雲原生」成為企業架構升級的新動能,而以K8S為代表的雲原生基礎設施已經被各行業廣泛接受。面對雲原生1.0時代單一應用生態缺少應用級容災能力、應用無法跨數據中心調度、應用與資源割裂等問題。
  • 產業網際網路時代,如何構建雲原生的安全運營中心?
    越來越多的客戶選擇公有雲作為承載業務的基礎設施,基於雲原生的方式搭建業務系統已經成為越來越多客戶數位化轉型中的必然選擇。網絡安全技術的發展史也可以說是信息系統架構的升級史,信息系統架構的升級變化往往會對網絡安全體系帶來新的挑戰,也繼而推動了網絡安全技術的升級與發展。
  • 雲原生最好的時代 KubeSphere為企業落地雲原生提供容器支持
    (原標題:雲原生最好的時代 KubeSphere為企業落地雲原生提供容器支持)
  • 開源巨頭 SUSE 收購 Rancher Labs,雲原生時代來臨
    作者 | 馬超責編 | 伍杏玲封圖 | rancher.com官網近日,全球最大的獨立開源公司SUSE宣布收購雲原生初始公司Rancher Labs。針對此交易,SUSE執行長Melissa Di Donato表示:「我們為客戶和合作夥伴創造更好的未來和可衡量的價值的願景指導了我們的決策並推動了業績增長。
  • 雲原生,為何而生?雲計算時代命題之終極解決方
    導語:3月24日,雲片技術開放日2019首站杭州,匯聚了雲片、個推、諧雲、有贊網際網路公司技術專家,共同討論雲原生趨勢下的架構演進之路。在過去幾年,雲原生技術飛速發展。以Kubernetes、Kubeflow為代表的雲原生技術讓「雲原生」從一個模糊的概念,強勢成長為通用技術。
  • 紅帽曹衡康:如何在用戶主導創新的雲原生時代取得領先優勢?
    進入到雲計算時代之後,技術創新的大門仿佛一下子被打開,大量的新概念、新技術如雨後春筍般的湧現出來。從早期的OpenStack、IaaS平臺,到中期的容器技術、微服務架構,再到現在的servicemesh服務網格技術、serverless無伺服器架構、雲原生技術,與雲計算相關的技術創新一直保持著極高的更新速度。
  • 騫雲:雲原生時代下的IT管理之痛
    一、雲原生不是趨勢,已是事實現如今,雲越來越普及,無論是個人專業用戶,還是企業用戶,上雲已經是普遍現象。伴隨著雲計算的快速發展,雲已逐步超越了虛擬化,各種雲原生服務日新月異。
  • 向雲計算要技術紅利,華為雲定義雲原生2.0時代
    11月30日,華為雲CTO張宇昕在「雲原生2.0,加速企業智能升級」活動上指出:雲原生的1.0時代,主要是面向網際網路行業;而雲原生2.0時代,則面向所有企業。雲原生2.0時代,政企在傳統應用上雲的基礎上,將基於雲原生技術開發新型雲原生應用,真正釋放雲計算技術紅利。華為雲也在今年9月提出「雲原生2.0」的基礎上,進一步推出了雲原生2.0全景圖。
  • 騰訊安全董志強:用雲原生安全鑄造產業網際網路時代的堅實底座
    12月19日,2020 Techo Park開發者大會在北京舉辦,騰訊雲首席安全官董志強出席並發表了以《用雲原生安全鑄造產業網際網路時代的堅實底座》為主題的演講。他表示,雲計算已成為產業網際網路和未來數位化變革的主要載體,而雲上的安全服務也應該像雲一樣,讓客戶能夠開箱即用、按需索取、按量付費。
  • 阿里雲發布雲原生架構白皮書 多維度評估雲原生架構成熟度
    從「壓迫感」到「掌控感」的力量轉變在雲計算高速發展的時代背景下,體會到數位化業務競爭所帶來的強烈「壓迫感」後,大量企業紛紛走上數位化轉型之路。數位化轉型使企業中大量原有業務不得不開始數位化演進。雲時代下,企業需要新技術架構,使之更好地利用雲計算優勢,讓業務更敏捷、成本更低、可伸縮性更強。而雲原生架構的應用意義正在於此。數據顯示*,2020 年,超過 50% 的全球組織在生產環境中運行容器化應用程式,到 2022 年將超過 75% 。在中國*,截止到 2018 年底,已有 96% 的IT企業在生產環境部署容器化應用。
  • 乘風破浪的雲原生
    為了及早發現故障並快速做出響應,洋蔥學院也採用了阿里雲原生監控系列產品,可以覆蓋到各類監控報警問題,極大地縮短問題發現時間。從2013年決定全面上雲,到現在擁抱雲原生新趨勢,洋蔥學院以一貫的超前意識,表達著這個時代網際網路公司該有的態度。
  • 一站式打卡「雲原生」時代的高效開發:微服務和資料庫還能這樣玩
    在這場近90分鐘腦力風暴,與近2小時實戰修煉中,主題直奔當下火熱的「雲原生」,並結合雲原生時代的「微服務」與「資料庫」,深入淺出揭開一站式高效開發的秘籍。12月19日,DevRun開發者沙龍華為雲南京雲原生專場在南京成功舉辦。
  • 雲原生資料庫正當時,華為雲TechWave雲原生2.0技術峰會等你來
    雲原生2.0時代,資料庫將面臨怎樣的變革?雲原生資料庫將如何如何加速企業數位化轉型,助其成為「新雲原生企業」。12月30日,來華為雲TechWave雲原生2.0技術峰會,聽華為雲資料庫技術專家解讀雲原生資料庫的新動向。
  • ...2020中國科創產業新銳Top50」,目標雲原生時代的ServiceNow!
    多雲和雲原生持續普及,企業IT管理問題逐漸顯現:統一運維難度大、效率低、DevOps和雲如何整合、雲上成本高且難以統計分析等,給企業IT管理帶來了巨大挑戰。騫雲科技SmartCMP是領先的面向雲原生的管理平臺,統一管理公有雲,私有雲,容器上的幾百上千種雲原生服務,具備強大的服務編排、自動化、自服務能力。
  • 雲原生時代到來 KubeSphere容器平臺服務企業落地雲原生
    原標題:雲原生時代到來 KubeSphere容器平臺服務企業落地雲原生   「軟體定義是不可扭轉的趨勢,通過這種方式可以更好地做資源
  • 分布式系統架構與雲原生—阿里雲《雲原生架構白皮書》導讀
    1 雲原生與分布式系統架構的關係  1.1 雲原生架構的定義  《雲原生架構白皮書》中對於雲原生架構的定義為「基於雲原生技術的一組架構原則和設計模式的集合,旨在將雲應用中的非業務代碼部分進行最大化的剝離,從而讓雲設施接管應用中原有的大量非功能特性(如彈性、韌性、
  • 5G和雲原生時代,技術的下半場從哪裡開始
    隨著5G/晶片/區塊鏈等等新技術的不斷成熟、雲計算的普及和雲原生時代帶來的諸多便捷,開發者和架構師們眼前的挑戰也不再只是 0-1 的建設問題,技術如何更多地帶來業務價值成為了一個值得討論的話題。由極客邦科技舉辦的QCon全球軟體開發大會2020(深圳站)上,阿里巴巴集團研究員,阿里雲智能視頻雲業務負責人林昊(花名畢玄)發表了主題演講《5G和雲原生時代的技術下半場》,以5G典型場景音視頻為例,探討相關技術和技術人的下半場,以下內容為演講整理。