Java程序是如何執行的?

本節從總體來看一下Java中的精髓.java

Java介紹

算法

Java和JDK的關係

JDK(Java Development Kit) Java開發工具包,它包括:編譯器,Java運行環境(JRE, Java Runtime Environment), JVM(Java虛擬機),監控和診斷工具等,而Java則表示一種開發語言.數據庫

Java程序是怎麼執行的?

  1. 先把Java代碼編譯成字節碼,也就是把 .java類型的文件編譯成 .class類型的文件.這個過程的大體執行流程: Java源代碼 -> 詞法分析器 -> 語法分析器 -> 語義分析器 -> 字節碼生成器  ->最終生成字節碼,其中任何一個節點執行失敗就會形成編譯失敗;
  2. 把class文件放置到Java虛擬機,這個虛擬機一般指的是Oracle官方自帶的Hotspot JVM;
  3. Java虛擬機使用類加載器(Class Loader)裝載class文件;
  4. 類加載完成以後,會進行字節碼校驗,字節碼校驗經過JVM解釋器會把字節碼翻譯成機器碼交由操做系統執行.但不是全部代碼都是解釋執行的,JVM對此作了優化, 好比, 以Hotspot虛擬機來講, 它自己提供了JIT (Just In Time)也就是咱們一般所說的動態編譯器,它可以在運行時將熱點代碼編譯成機器碼,這個時候字節碼就變成了編譯執行.

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)、Dubbo、Zookeeper、SpringCloud等。

6.數據庫

MySQL經常使用引擎的掌握、MySQL前綴索引、回表查詢、數據存儲結構、最左匹配原則、MySQL的問題分析和排除方案、MySQL讀寫分離的實現原理以及MySQL的常見優化方案等。Redis的使用場景、緩存雪崩和緩存穿透的解決方案、Redis過時淘汰策略和主從複製的實現方案等。

7.Java虛擬機

虛擬機的組成、垃圾回收算法、各類垃圾回收器的區別、Java虛擬機分析工具的掌握、垃圾回收器經常使用的調優參數等。

8.其餘

經常使用算法的掌握、設計模式的理解、網絡知識和常見Linux命令的掌握等。


相關題目 

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中如何獲取明天此刻的時間?

答:JDK8以前使用Calendar.add()方法獲取,代碼以下:

Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE,1);
System.out.println(calendar.getTime());

JDK8有兩種獲取明天時間的方法。

方法一,使用  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個字節(16bit),因此放一箇中文是沒問題的。

7.Java中會存在內存泄漏嗎?請簡單描述一下。

答:一個再也不被程序使用的對象或變量一直被佔據在內存中就形成了內存泄漏。

Java中得內存泄漏的常見情景以下:

  • 長生命週期對象持有短生命的引用,好比,緩存系統,咱們加載了一個對象放在緩存中,而後一直不使用這個緩存,因爲緩存的對象一直被緩存引用得不到釋放,就形成了內存泄漏。
  • 各類鏈接未調用關閉方法,好比數據庫Connection鏈接,未顯性地關閉,就會形成內存泄漏。
  • 內部類持有外部類,若是一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即便那個外部類實例對象再也不被使用,但因爲內部類持有外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會形成內存泄漏;
  • 改變哈希值,當一個對象被存儲進HashSet集合中之後,就不能修改這個對象中的那些參與計算哈希值的字段了,不然對象修改後的哈希值與最初存儲進HashSet集合中的哈希值就不一樣了,在這種狀況下,即便在contains方法使用該對象的當前引用做爲的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也將致使沒法從HashSet集合中單獨刪除當前對象,形成內存泄露。
相關文章
相關標籤/搜索