第 1-1 课:Java 程序是如何执行的?
了解任何一門語言的精髓都是先俯覽其全貌,從宏觀的視角把握全局,然后再深入每個知識點逐個擊破,這樣就可以深入而快速的掌握一項技能。同樣學習 Java 也是如此,本節就讓我們先從整體來看一下 Java 中的精髓。
Java 介紹
Java 誕生于 1991 年,Java 的前身叫做 Oak(橡樹),但在注冊商標的時候,發現這個名字已經被人注冊了,后來團隊的人就在咖啡館討論這件事該怎么辦,有人靈機一動說叫 Java 如何,因為當時他們正在喝著一款叫做 Java 的咖啡。就這樣,這個后來家喻戶曉的名字,竟以這種“隨意”的方式誕生了,并一直沿用至今。
Java 發展歷程:
- 1990,Sun 成立了“Green Team”項目小組
- 1991,Java 語言前身 Oak(橡樹)誕生
- 1995,Oak 語言更名為 Java
- 1996,Java 1.0 發布
- 1997,Java 1.1 發布
- 1998,Java 1.2 發布
- 2000,Java 1.3 發布
- 2000,Java 1.4 發布
- 2004,Java 5 發布
- 2006,Java 6 發布
- 2011,Java 7 發布
- 2014,Java 8 發布
- 2017,Java 9(非長期支持版)發布
- 2018.03,Java 10(非長期支持版) 發布
- 2018.09,Java 11(長期支持版)發布
- 2019.03, Java 12(非長期支持版) 發布
注:長期支持版指的是官方發布版本后的一段時間內,通常以“年”為計數單位,會對此版本進行持續維護和升級。
版本發布時間 Java 10 之后,官方表示每半年推出一個大版本,長期支持版本(LTS)每三年發布一次。
Java 和 JDK 的關系
JDK(Java Development Kit)Java 開發工具包,它包括:編譯器、Java 運行環境(JRE,Java Runtime Environment)、JVM(Java 虛擬機)監控和診斷工具等,而 Java 則表示一種開發語言。
Java 程序是怎么執行的?
我們日常的工作中都使用開發工具(IntelliJ IDEA 或 Eclipse 等)可以很方便的調試程序,或者是通過打包工具把項目打包成 jar 包或者 war 包,放入 Tomcat 等 Web 容器中就可以正常運行了,但你有沒有想過 Java 程序內部是如何執行的?
其實不論是在開發工具中運行還是在 Tomcat 中運行,Java 程序的執行流程基本都是相同的,它的執行流程如下:
Java 程序執行流程圖如下:
Java 虛擬機是如何判定熱點代碼的?
Java 虛擬機判定熱點代碼的方式有兩種:
- 基于采樣的熱點判定
主要是虛擬機會周期性的檢查各個線程的棧頂,若某個或某些方法經常出現在棧頂,那這個方法就是“熱點方法”。這種判定方式的優點是實現簡單;缺點是很難精確一個方法的熱度,容易受到線程阻塞或外界因素的影響。
- 基于計數器的熱點判定
主要就是虛擬機給每一個方法甚至代碼塊建立了一個計數器,統計方法的執行次數,超過一定的閥值則標記為此方法為熱點方法。
Hotspot 虛擬機使用的基于計數器的熱點探測方法。它使用了兩類計數器:方法調用計數器和回邊計數器,當到達一定的閥值是就會觸發 JIT 編譯。
方法調用計數器:在 client 模式下的閥值是 1500 次,Server 是 10000 次,可以通過虛擬機參數: -XX:CompileThreshold=N 對其進行設置。但是JVM還存在熱度衰減,時間段內調用方法的次數較少,計數器就減小。
回邊計數器:主要統計的是方法中循環體代碼執行的次數。
由上面的知識我們可以看出,要想做到對 Java 了如之中,必須要好好學習 Java 虛擬機,那除了 Java 虛擬機外,還有哪些知識是面試必考,也是 Java 工程師必須掌握的知識呢?
1. Java 基礎中的核心內容
字符串和字符串常量池的深入理解、Array 的操作和排序算法、深克隆和淺克隆、各種 IO 操作、反射和動態代理(JDK 自身動態代理和 CGLIB)等。
2. 集合
集合和 String 是編程中最常用的數據類型,關于集合的知識也是面試備考的內容,它包含:鏈表(LinkedList)、TreeSet、棧(Stack)、隊列(雙端、阻塞、非阻塞隊列、延遲隊列)、HashMap、TreeMap 等,它們的使用和底層存儲數據結構都是熱門的面試內容。
3. 多線程
多線程使用和線程安全的知識也是必考的面試題目,它包括:死鎖、6 種線程池的使用與差異、ThreadLocal、synchronized、Lock、JUC(java.util.concurrent包)、CAS(Compare and Swap)、ABA 問題等。
4. 熱門框架
Spring、Spring MVC、MyBatis、SpringBoot
5. 分布式編程
消息隊列(RabbitMQ、Kafka)、Double、Zookeeper、SpringCloud 等。
6. 數據庫
MySQL、Redis
7. Java 虛擬機
虛擬機的組成、垃圾回收算法、各種垃圾回收器、Java 虛擬機分析工具、Java 虛擬機常用調優配置等。
8. 其他
常用算法、設計模式
值得慶幸的是以上所有內容都包含在本課程中,接下來就讓我們一起學習,一起構建 Java 的認知體系吧。
相關面試題
1. Java 語言都有哪些特點?
答:Java 語言包含以下特點。
- 面向對象,程序容易理解、開發簡單、方便;
- 跨平臺,可運行在不同服務器類型上,比如:Linux、Windows、Mac 等;
- 執行性能好,運行效率高;
- 提供大量的 API 擴展,語言強大;
- 有多線程支持,增加了響應和實時交互的能力;
- 安全性好,自帶驗證機制,確保程序的可靠性和安全性。
2. Java 跨平臺實現的原理是什么?
答:要了解 Java 跨平臺實現原理之前,必須先要了解 Java 的執行過程,Java 的執行過程如下:
Java 執行流程:Java 源代碼(.java)-> 編譯 -> Java 字節碼(.class) ->通過 JVM(Java 虛擬機)運行 Java 程序。每種類型的服務器都會運行一個 JVM,Java 程序只需要生成 JVM 可以執行的代碼即可,JVM 底層屏蔽了不同服務器類型之間的差異,從而可以在不同類型的服務器上運行一套 Java 程序。
3. JDK、JRE、JVM 有哪些區別?
答:了解了 JDK、JRE、JVM 的定義也就明白了它們之間的區別,如下所述。
- JDK:Java Development Kit(Java 開發工具包)的簡稱,提供了 Java 的開發環境和運行環境;
- JRE:Java Runtime Environment(Java 運行環境)的簡稱,為 Java 的運行提供了所需環境;
- JVM:Java Virtual Machine(Java虛擬機)的簡稱,是一種用于計算設備的規范,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的,簡單來說就是所有的 Java 程序都是運行在 JVM(Java 虛擬機)上的。
總體來說,JDK 提供了一整套的 Java 運行和開發環境,通常使用對象為 Java 的開發者,當然 JDK 也包含了 JRE;而 JRE 為 Java 運行的最小運行單元,一般安裝在 Java 服務器上,所以 JDK 和 JRE 可以從用途上進行理解和區分。JVM 不同于 JDK 和 JRE,JVM 是 Java 程序運行的載體,Java 程序只有通過 JVM 才能正常的運行。
4. Java 中如何獲取明天此刻的時間?
答:JDK 8 之前使用 Calendar.add() 方法獲取,代碼如下:
Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, 1); System.out.println(calendar.getTime());JDK 8 有兩種獲取明天時間的方法。
方法一,使用 LocalDateTime.plusDays() 方法獲取,代碼如下:
LocalDateTime today = LocalDateTime.now(); LocalDateTime tomorrow = today.plusDays(1); System.out.println(tomorrow);方法二,使用 LocalDateTime.minusDays() 方法獲取,代碼如下:
LocalDateTime today = LocalDateTime.now(); LocalDateTime tomorrow = today.minusDays(-1); System.out.println(tomorrow);minusDays() 方法為當前時間減去 n 天,傳負值就相當于當前時間加 n 天。
5. Java 中如何跳出多重嵌套循環?
答:Java 中跳出多重嵌套循環的兩種方式。
- 方法一:定義一個標號,使用 break 加標號的方式
- 方法二:使用全局變量終止循環
方法一,示例代碼:
myfor:for (int i = 0; i < 100; i++) {for (int j = 0; j < 100; j++) {System.out.println("J:" + j);if (j == 10) {// 跳出多重循環break myfor;}} }方法二,示例代碼:
boolean flag = true; for (int i = 0; i < 100 && flag; i++) {for (int j = 0; j < 100; j++) {System.out.println("J:" + j);if (j == 10) {// 跳出多重循環flag = false;break;}} }6. char 變量能不能存貯一個中文漢字?為什么?
答:char 變量可以存貯一個漢字,因為 Java 中使用的默認編碼是 Unicode ,一個 char 類型占 2 個字節(16 byte),所以放一個中文是沒問題的。
7. Java 中會存在內存泄漏嗎?請簡單描述一下。
答:一個不再被程序使用的對象或變量一直被占據在內存中就造成了內存泄漏。
Java 中的內存泄漏的常見情景如下:
- 長生命周期對象持有短生命的引用,比如,緩存系統,我們加載了一個對象放在緩存中,然后一直不使用這個緩存,由于緩存的對象一直被緩存引用得不到釋放,就造成了內存泄漏;
- 各種連接未調用關閉方法,比如,數據庫 Connection 連接,未顯性地關閉,就會造成內存泄漏;
- 內部類持有外部類,如果一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由于內部類持有外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內存泄露;
- 改變哈希值,當一個對象被存儲進 HashSet 集合中以后,就不能修改這個對象中的那些參與計算哈希值的字段了,否則對象修改后的哈希值與最初存儲進 HashSet 集合中時的哈希值就不同了,在這種情況下,即使在 contains 方法使用該對象的當前引用作為的參數去 HashSet 集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從 HashSet 集合中單獨刪除當前對象,造成內存泄露。
總結
以上是生活随笔為你收集整理的第 1-1 课:Java 程序是如何执行的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多图带你彻底理解Java中的21种锁!
- 下一篇: WebApi开启CORS支持跨域POST