1. 程式人生 > >Java面試基本知識

Java面試基本知識

alloc 正向代理 like write 工廠方法模式 內部 parent jre digester

Java基本知識

基本知識

  • 服務器:Tomcat 支持Servlet jsp JBoss 開源應用服務器 Apache:最廣泛的http服務器,只支持靜態網頁

  • String是長度不可變,用+=的時候會生成一個新的String對象,StringBuffer和StringBuilder是可變長度,StringBuffer為線程安全

  • 並發編程:原子性 客觀性 有序性

  • serializable : 靜態不能被序列化,被transient修飾的也不能被序列化

  • 面向過程和面向對象:

    • 面向過程:速度快,效率高 難維護,難擴展 ,難服用

    • 面向對象:速度較面向過程慢,但易維護,易擴展,易復用

  • jdk和jre的區別: jdk的bin下有javac jre的bin下沒有

  • 基本數據類型 double 在判斷相等時,為什麽不可以用==?答案:存儲精度問題,一般使用閾值, a-b 小於這個閾值,一般就認為相等。

  • 並行:兩個或多個事件,在同一時刻發生。並發:兩個或多個事件,在同一時間間隔發生。

  • Object並沒有實現CallAble方法,如果在Object調用會拋出異常

  • 子類和父類同名,會覆蓋,但是可以在子類中super調用

  • a對應的ASCII編碼為 97 A為65 0為45

  • 如果一個局部變量沒有賦初始值不可調用

  • 進程基本狀態:縣城:比進程更小的獨立運行單位,同一進程中可有多個線程並發執行。線程: cpu 調度基本單位。進程: cpu 分配資源基本單位。

  • Integer.parseInt(s,x)s代表轉換的數字,x代表轉換為多少進制

  • 若try,finally都有retrun語句,則忽略try中的return

  • 內部類

    • 成員內部類

    • 局部內部類

    • 靜態內部類

    • 匿名內部類(繼承一個方法或者實現一個接口)

    • 外部類的成員不能訪問內部類的成員(static內部類除外) 內部類可以訪問外部類的所有成員。

  • 端口號來區分進程

  • java 反射

    • 可以在運行時獲取類的信息
  • StringBuffer 底層是char[] 擴容一個擴容 2倍+2 (左移1)

  • 常量池中只會存在一個值相同的String對象

  • 局部變量沒有默認值,必須手動賦值

  • Java接口的修飾符只可以是abstract和public的

  • Error和Exception的區別

    • Error 類一般指的為虛擬機的異常,對於這種異常,程序本身無法恢復和預防

    • Exceptio 表示程序可以處理的異常,即程序編寫錯誤出現的異常。

  • Final初始化只有兩個地方 定義和構造函數

  • 輸出兩位數 System.out.print("%.2f",cc);

  • Java同步鎖

    • 每一個對象自己都帶了一把鎖,即monitor鎖,monitor是線程私有的數據結構,每個線程都有一個可用的monitor record列表,同時還有一個全局可用的列表,每一個被鎖住的對象都會和monitor關聯,Monitor中有一個owner字段存放擁有改對象的線程的唯一標識,表示該鎖被這個線程占有,

    • 鎖粗化:將多個加鎖操作連起來形成一個範圍更大的鎖

  • Java8新特性:

    • 允許在接口中添加一個方法 用default關鍵字修飾

    • lambda表達式

    • 函數式接口

    • dateApi

    • 可重復註解

集合

  • hashmap 初始化不會初始化數組,而是在put操作的時候初始化數組

  • TreeSet :實現compareTo方法,定義一個類,實現conparator,底層實現為紅黑樹

  • HashSet: HashCode不同 一定不是同一個元素, 相同則再比較啊equals 底層為二叉樹

  • Collection有iterator 所以set和list有 map需要用entryset和keyset

  • hashSet不是線程安全

  • 優先級隊列的頭是按照指定規則排序方式確定的最小元素

  • TreeMap根據鍵的自然順序排序

  • hash查找的時間復雜度與原始數量無關,hash表查找元素的時候是直接通過計算hash值來確定元素的位置,從而直接訪問元素,所欲hash表的插入,刪除,查找都是O(1)

  • 阻塞隊列:

    • BlockingQueue 阻塞隊列:如果進行put操作而隊列中沒有元素,則會阻塞put操作直到有元素

      • ArrayBlockingQueue 其構造函數必須帶一個 int 參數,來指明其大小。其所含的對象是由 FIFO 順序排列的。

      • linkedBlockingQueue: 大小不一定,若構造函數傳入 int,則 BlockingQueue 有大小限制,否則大小為 Integer.MAX_VALUE,其所含的對象是由 FIFO 順序

  • LinkList是Queue的實現

  • HashSet基於HashMap實現,允許null 不允許為重復,

  • Concurrenthashmap : 線程安全的HashMap,在get時候不需要加鎖,put必須加鎖

  • ConcurrentMap 允許一遍叠代一遍更新

線程

  • 各個線程共享進程資源,也可以獨立調度,線程是CPU調度的基本單位

  • 競態條件:

    • 由於不恰當的執行順序而產生不一樣的結果,基於一種可能失效的觀察結果來做出判斷。
  • 線程池的狀態

    • 剛被創建的時候處於 running狀態

    • 調用shutdown方法後,屬於shutdown狀態,此時不接受新的線程,等待已經有的線程任務執行完畢

    • 調用shutdownNow方法後,進入stop狀態,此時不接受新的線程,並且嘗試終止正在執行的線程

    • 當處於shutdown或者stop狀態,並且所有線程已經銷毀,任務緩存隊列已經清空的時候,線程池進入terminated

  • synchronized VS lock

    • L是一個接口,S是一個關鍵字

    • S在發生異常的時候會自動釋放對象鎖,L發生異常如果沒有unlock則不會釋放鎖,所以要將unlock放在finally中

    • 通過L可以知道是否成功的獲得鎖, S不可以

    • L可以提高多個線程進行讀寫的效率

  • ThreadLoacl:ThreadLocal為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。ThreadLocl采用的是hash表的方式來為每一個線程提供副本

    • 類中有一個map,用來存儲每一個線程變量的副本,map的key為Threadlocal對象,value為該變量的線程副本。

    • 關鍵在ThreadLocalMap類中,他是ThreadLocal的靜態內部類,它實現了鍵值對的設置和獲取。每個線程對應一個ThreadlocalMap,從而實現了變量訪問在不同線程中的隔離。因為每個線程的變量都是自己特有的,完全不會有並發錯誤。

  • 公平鎖

    • 多個線程在等待一個鎖的時候按照申請鎖的順序來分配, Synchronized為非公平鎖
  • 自旋鎖

    • 當兩個或者兩個以上的線程並行執行的時候,我們就可以讓後面的線程稍微等一下,但不放棄處理器的執行時間,看看持有鎖的線程是否很快就釋放鎖,為了讓線程等待,我們需要讓線程執行一個忙循環,這就是自旋鎖。
  • Synchronized : 同步代碼塊和同步方法 , 同步方法對象鎖是this 靜態方法是所在類的class對象

  • synchronized關鍵字經過編譯後,會在同步代碼塊的前後分別形成moniterenter和moniterexit兩個字節碼指令,這兩個字節碼參數都需要一個reference類型的參數指明要鎖定和解鎖的對象,在執行moniterenter指令的時候首先要嘗試獲取對象的鎖,若這個對象還沒有被鎖定,或當前線程對應已經擁有那個鎖對象,把鎖的計數器+1,相應的在執行moniterexit時會將鎖的計數器-1,當計數器為零時,鎖被釋放。

  • java虛擬機可以從方法表中acc_aynchronized標誌位知道一個方法是否為同步方法,當一個方法是同步方法的時候,執行線程要求先成功持有moniter,才能執行方法

  • 多線程的問題:當多個線程操作一個線程共享語句的時候,一個線程只執行了語句的一部分,還沒有執行完,另一個線程參與執行,此時會引起共享數據的錯誤, 解決辦法:線程同步

  • ReenTrantLock: 可重入鎖,即現在占有這個鎖的線程可以重復進入,但是必須要重復退出 ,2. 可以中斷, 3. 可以設定獲取鎖的時間,在指定時間內沒有獲取到鎖,則會返回失敗,不會構成死鎖 4. 公平鎖:先來先得

  • 共享鎖:允許多個線程同時進入臨界區,但是共享額度是有限的,當額度用完了 其他線程還是要阻塞, 當額度為1時相當於lock

  • ReadWriteLock : 讀寫鎖,讀-讀不互斥,讀寫互斥,寫-寫也互斥

  • 線程池中的線程任務就是不斷檢查任務隊列是否有隊列並且不斷執行隊列中的任務

  • Sleep Wait

    • Sleep是線程的方法而wait是Object類的方法,sleep只釋放cpu的執行權

    • Sleep不釋放對象鎖而wait釋放對象鎖

    • Sleep在指定時間後會自動回到就緒狀態,而wait需要喚醒

  • 同步:當發出一個調用的時候,在沒有得到結果以前,等待調用結果,期間當前程序阻塞

  • 異步:調用在發出後立即返回,不等待調用結果,而是在結果出來以後被調用者通過狀態通知調用者,

  • 阻塞:當結果沒有返回前當前線程會被掛起,知道等到結果返回

  • 非阻塞:不能立刻得到結果之前,該調用不會阻塞當前線程。

  • BIO:同步阻塞

  • NIO:同步非阻塞

  • AIO:異步非阻塞

NIO

  • newIO是一個新的IO

  • Io:面向流、阻塞、無選擇器; nio:面向緩沖,非阻塞 io,有選擇器;

  • NIO:nio的效率比io高,nio是面對緩存,而io是直接面對流,nio是非堵塞,而io是堵塞

  • channel:任何來源的目的地都需要通過一個channel對象,一個Buffer是一個容器對象,發給channer的數據都需要先放到buffer中,從channel讀取的數據都需要放到buffer中

  • 使用buffer讀寫數據: 1. 寫入數據到buffer 2. 調用filp方法 3. 從buffer中讀取數據 4. 調用clear和compact方法

  • 想buffer中寫入數據的時候,buffer會記錄寫入了多少行,讀取數據完成以後需要清空緩沖區,讓他可以再次被寫入,有兩種方式能清空緩存區, 1. clear 清空所有緩存區 2. compact清除已經讀取過的數據

  • channel類型

    • Filechannel:從文件讀取數據

    • Datagramchannel:讀寫 udp 的網絡協議數據。

    • Socketchannel:讀寫 tcp 網絡協議數據。

    • Serversocketchannel:可以監聽 tcp 連接。

  • 文件讀取部分需要三步:從FileInputStream獲取Channer, 創建Buffer 從Buffer讀取數據

      public static void main(String[] args) throws IOException {
            FileInputStream fileInputStream = new FileInputStream(new File("Demo1.java"));
            FileChannel channel = fileInputStream.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
    
            FileOutputStream fileOutputStream = new FileOutputStream(new File("Demo2"));
            FileChannel outChannel = fileOutputStream.getChannel();
    
            int len = 0;
            long size = 0;
    
            while ((len = channel.read(buffer)) != -1) {
                size = size + len;
                buffer.flip();
                outChannel.write(buffer);
                buffer.clear();
            }
            System.out.println(size / 1024.0);
    
            fileInputStream.close();
            fileOutputStream.close();
            channel.close();
            outChannel.close();
    
        }
  • selector是一個對象,可以註冊到多個channel,監聽各個channel上發生的事情,並且能夠根據事情來決定channel的讀寫,這樣可以通過一個線程管理多個channel,處理大量網絡連接

    • selector只可以管理異步的channel,socketchannel SelectionKey key = channel2.register(selector, SelectionKey.OP_READ);

      • 第二個參數:通道觸發一個事件即ready 所選參數 1. 連接 connect 2. 準備好接收數據 accept 3. 數據可讀 read 4. 數據可寫 write 可以註冊多個事件,Int interest=SelectionKey.OP_READ|SelectionKey.OP_ACCEPT
    • 當selector上註冊了一個或多個通道,可以調用重載的方法返回你感興趣的事件 selector.select(SelectionKey.OP_ACCEPT);

    • Int select():阻塞到至少有一個通道在你註冊的事件上就緒; Int select(long timeout):與select()一樣,只是最長只會阻塞 timeout ms;Int selectnow(),不阻塞,不管什麽通道就緒都立即返回,若自從前一次選擇操作後,沒有通道變為可選的,則直接返回 0。

Web編程

  • Servlet聲明周期,當初始化web容器或者第一次訪問Servlet時會初始化Servlet,調用構造方法和init,當請求Servlet時會通過doserivice判斷調用那個方法,Servlet銷毀時調用destory方法

  • Cookie放在客戶端

    • Cookie默認是會話級別的,存儲在瀏覽器中,希望保存Cookie是需要設置Cookie的最大存活時間。

    • Cookie是客戶端保持Http狀態的解決辦法, Session 是服務端保持Http狀態的解決辦法

  • Session

    • 一個Session對應的一個SessionID

    • 當創建一個Session時,會將SessionID放在Cookie中來傳輸,下次瀏覽器訪問的時候會帶上這個SessionID,瀏覽器就知道當前用戶對應的Session(也可以通過URl來傳輸)

    • 關閉瀏覽器只會使客戶端session失效,服務端不會(但是服務端session有最大存活時間)

  • Filter 的應用:

    • 禁用瀏覽器的緩存。

    • 字符編碼過濾器。若沒有過濾器則在每一個請求頁面中都要寫request.setCharacterEncoding,

    • 檢測用戶是否登錄的 filter。

  • forword和redirect

    • 是服務器請求資源,服務器直接訪問目標地址的url,把url相應的內容讀取出來,然後發送給瀏覽器,瀏覽器根本不知道服務器發送的內容從哪裏取得,所以地址欄還是原來的地址

    • redirect 是讓瀏覽器去訪問地址,所以地址欄會改變,相當於兩個request和response

    • forward 轉發頁面和轉發到的頁面可以共享數據 redirect不能

    • forward 只能在web應用之間轉發, redirect可以定位到同一個站點上的其他資源

    • forward / 代表web應用根目錄, Redirect / 代表棧頂根目錄

  • jsp九大內置對象

    • request

    • session

    • appication

    • pageContext

    • request

    • out

    • page

    • config

    • exception

  • jsp動作

    • jsp:include :包含

    • jsp:userBean : 尋找或者實例化一個bean

    • jsp:setProperty:傳遞參數

    • jsp:forward 請求轉發

  • 如何實現 servlet 單線程模式?答案:要實現單線程模式,可以在配置文件中修改isThreadSafe 屬性,比如,<%@page isThreadSafe=”false”%>

  • 靜態包含, 在編譯前就將兩個jsp頁面包含,最後生成一個Servlet

  • 動態包含: 先把兩個jsp頁面解析為Servlet 在整合

  • Hiberante 1+N的問題

    • 一對多: 在1的一方查詢到對象,由於關聯的存在,需要將n個關聯對象取出來,因為集合的數量為n還要發n條sql 所以一共發送n+1

    • 多對一:多的一方查詢到了n個對象,發出了n條語句,因為n個對象關聯一個對象所以要再發送一條語句 所以為n+1

    • iterator:查詢時會先去緩存中尋找 然後如果沒有則去數據庫 為n+1

  • Hibernate Load 和 Get區別

    • 如果沒有查詢到對象,get返回null,而load拋出異常

    • Load返回實體的代理類,而get返回實體類

    • load可以利用二級緩存來查詢數據,而get只能用內部緩存,如果內部緩存沒有則會跳過二級緩存直接查詢數據庫

    • 我們用Session.load加載一個對象時不會產生Sql語句,得到的只是一個代理對象,當用到其他字段的時候才會發送查詢語句,session.get不管我們是否使用這個對象都會發送sql語句

xml

  • XML解析的三種方式

    • sax:不需要讀入整個文件就可以解析出文件內容,是一種逐步解析的方法,適合大規模的解析,事件驅動,不能修改內容,順序查詢

    • dom:將整個文檔讀入內存,建立dom樹,支持修改,可隨機查詢

    • digester:將xml轉化為javaBean

數據庫

  • 索引添加的位置

    • 經常需要搜索的列

    • 作為主鍵的列

    • 經常用在連接的列

    • 經常需要進行範圍搜索,索引已經排序,指定的範圍是連續的

    • 經常需要排序的列

  • 什麽情況會使得索引失效

    • 條件中有or(若想在or中使用索引必須在全部的條件段都添加索引)

    • like查詢以%開頭

    • 若數據類型為字符串,則需要用“”引起來否則不使用索引

    • mysql估計使用全表掃描比索引快

    • 對索引進行運算

    • b-樹 is null 會用 is not null 不會用

  • sql優化

    • 盡量不要全表掃描 在where或者order by的列上添加索引

    • 盡量避免在where子語句中有where num is null 這樣會進行全表掃描

    • 避免在where中用or 若一個字段有索引,另一個沒有 則會全表

    • 避免在where <>or != 全表掃描

    • 使用復合索引的時候需要,必須用到改索引的第一個字段

  • 索引的缺點:

    • 創建和維護索引要耗費時間。

    • 索引需要占用物理空間,除了數據表占數據空間以外,每一個索引還要占物理空間。

    • 當對表中數據進行增加、刪除和修改時,索引也要動態維護,這樣就降低了數據的維護速度

  • Redis是一個Nosql數據庫,高並發,高性能,面向Key-value

  • 數據庫的範式:

    • 第一範式:強調列的原子性,列不能再分為其他幾列,屬性不可分。

    • 首先是 1NF,另外包含兩個部分, 1)一個表必須有主鍵 2)沒有包含在主鍵中的列必須完全依賴於主鍵,而不能只依賴於主鍵的一部分

    • 首先是 2NF,非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴,即不能存在非主鍵 A 依賴於非主鍵 b,非主鍵 b 依賴於主鍵的情況,消除傳遞依賴

  • 樂觀鎖和悲觀鎖:

    • 悲觀所: 每次別人拿數據的時候都會認為別人會修改這個數據,所以每次在使用數據的時候都會對數據上鎖,這樣別人想使用這個數據就會Block知道它拿到鎖,傳統的關系型數據庫用到了很多,比如行鎖,寫鎖。都是在操作之前上鎖

    • 樂觀鎖: 樂觀的以為每次使用數據的時候別人都不會修改數據,所以不會上鎖,當別人在更新數據的時候會判斷一下再次期間有沒有別人更新這個數據,具體實現的方式為,為每個表增加一個字段,表示版本號,當更新的時候判斷需要更新的版本號和數據庫中版本號,如果大於,則更新,若小於則不更新。

  • 數據庫的排它鎖和共享鎖

    • 共享鎖(讀鎖):當一個事務對一個對象上了共享鎖,其他事務只能對這個對象加共享鎖,只能讀取,不能修改

    • 排它鎖(寫鎖):如果事務T對數據A加上排他鎖後,則其他事務不能再對A加任任何類型的封鎖。獲準排他鎖的事務既能讀數據,又能修改數據。

  • mysql怎麽判斷是否使用了索引,可以在select 前面添加關鍵字eaplain 返回的數據中key為名字的那列為null 則沒有使用索引 強制使用索引select * from tablename from index(index_name);

  • sql:

    • Select * from tablename orderby liename limit m,n (從 m+1 條開始,取 n 條數據)。

    • Select a.,b. from a inner join b on a.id=b. parent_id; 內連接

    • Select a.,b.from a left join b on a.id=b. parent_id; 左外連接,左表的全部元素都有

    • Select a.,b.from a right join b on a.id=b. parent_id; 右外連接,右表的全部元素都有

    • Select a.,b.from a full join b on a.id=b. parent_id;

      • 完全連接返回左邊和右表中所有行,若某行在另外一個表中無匹配,則另一表的選擇列表列包含空值)
    • sql不等於<>

設計模式

  • 代理設計模式

    • 代理類和委托類有相同的接口,代理類的對象本身並不實現具體的服務,而是通過調用委托類中具體的方法來提供特定的服務。
  • 如果理解代理和裝飾, 代理類可以對他的用戶隱藏一個對象的具體信息,所以代理是在內部生成一個代理對象,構造函數為空,裝飾的構造函數的參數為一個對象,就是對這個傳遞進來的對象進行裝飾

  • 觀察者模式

    • 當被觀察者的行為狀態發生改變的時候會通知觀察者來進行相應的操作(老鼠和貓, 過馬路都是, 監聽器)

    • 一個對象的改變需要通知其他的對象。

    • java實現方式:觀察者實現統一的接口,然後將觀察者添加到被觀察者類中的一個集合,當觀察者某個狀態改變的時候會遍歷集合中的放啊並且調用對應的方法 (Observer 接口 Observable 類)

  • 工廠模式

    • 出現了大量的產品需要創建,並且實現了相同的接口,可以通過工廠方法模式進行創建,一個工廠裏,不同方法創建不同的類,根據傳入進去的參數不同產生不同的類。
  • 抽象工廠模式

    • 創建工廠的工廠,在擴展程序的時候無需修改工廠類,直接通過抽象工廠模式創建一個新的工廠類,增強了程序的擴展性。
  • 建造者模式

    • 工廠模式提供的是創建單個對象的模式,而建造者模式則是將各種產品集中起來進行管理,用來創建復合對象。
  • 原型模式

    • 該模式的思想就是將一個對象作為原型,對其進行復制、克隆,產生一個和原對象類似的新對象,適用於產生一個新對象所需要的代價比較大的情況, 淺拷貝實現 Cloneable,重寫,深拷貝是通過實現 Serializable 讀取二進制流。
  • 訂閱-發布模式

    • 觀察者模式中觀察者是由被觀察者觸發調用的,而訂閱發布模式是由調度中心來調度,所以觀察者模式會存在依賴,這個就不會
  • 適配器模式

    • 將某個類的接口轉換為客戶希望的接口,是兩個不相容接口之間的橋梁,結合了兩個獨立的接口的功能。

      • 類的適配器:當希望講一個類轉換為滿足一個接口類的時候可以集成這個類並且實現這個接口

      • 接口的適配:當我們只是希望實現一個接口中的某些方法的時候可以先用一個抽象類實現接口中的方法,然後我們繼承這個抽象類實現我們所想實現的方法就可以

      • 對象的適配:希望將一個對象轉換為滿足一個新接口的對象,創建一個wapper類,包含原來類和新接口,調用原類的實例的方法

  • 外觀模式

    • 解決類和類之間的依賴關系,將他們的關系放在一個facede類中,改模式沒有涉及到接口, 將幾個向關聯的類放在一個類中,在類中編寫邏輯調用方法。
  • 橋接模式:把事物和具體的實現分開,使他們可以獨自變化 jdbc

設計模式在JAVA中的應用

- 單例模式 Runtime

- 靜態工廠 :Integer.valueOf

- 叠代器模式:in

- 原型設計 clone

- 適配器模式  inputStreamReader

- 橋接模式 jdbc

- 裝飾模式:Reader和BufferREader

- Drivermanager.getConnection

JVM

  • 若有一個類加載請求,先檢查是否已經被加載,如果沒有被加載,則調用父類加載器的loadclass方法,若父類加載器為空,則默認使用啟動類加載器作為父類加載器,若父類加載器失敗,拋出異常,再調用自己的findclass方法進行加載

  • 類的初始化順序:加載class文件,靜態變量初始化(子類和父類 執行的為出現順序) 父類的變量,父類構造代碼塊,父類構造器,子類變量,子類構造代碼塊,子類構造函數

  • Java編譯的過程

    • 解析和填充符號表的過程

    • 註解處理

    • 分析與生成字節碼過程

  • JVM啟動加載類的時候

    • 運行bootstarp classLoader 加載核心api,然後執行ext classloader加載擴展的API,最後app classloader 加載classpath目錄下的class,最基本的流程。

    • 通過classloader加載類的時候不會對類進行解析,也不會初始化, forName方法會解析和初始化class

  • JVM參數

    • Xmx:最大堆大小

    • Xms: 最小堆大小

    • Xmn: 年輕代堆大小

    • Xss: 堆的大小

    • XXSurvivoRatio: 年輕代中eden和survivo區的大小比較

  • 類的加載過程

    • 加載

      • 通過全類名獲取二進制流

      • 將字節流表示的靜態存儲結構轉換為方法區的運行時數據結構

      • 生成class文件

    • 驗證

      • 保證class文件的字節流中包含的信息是否符合當前虛擬機的要求
    • 準備

      • 為變量分配內存,並設置變量的初始值
    • 解析

      • 將常量池中的符號引用變為直接引用
    • 初始化 : 初始化這個類,如果這個類有父類先初始化父類。

  • 類加載器:

    • 啟動類加載器 lib

    • 擴展類加載器 lib/ext

    • 應用程序類加載器 加載classpath 的class

  • 內存泄露,對象是可達的,對象以後不會被用到

  • 內存溢出(程序申請內存時沒有足夠的內存分配)

  • java虛擬機操作碼只有一個字節

  • 符號引用的目標不一定加入內存,直接引用的目標一定加入了內存

  • 垃圾回收

    • GCRoot : 通過一系列的GCRoot對象作為起始點,從這些節點開始向下搜索,走過的路徑為引用鏈,當一個對象到GcRoot沒有一個引用鏈,則該回收,若對象沒有引用鏈相連接,那麽它會被標記和進行一次篩選,若對象乜有重寫finalize方法或者已經被調用,則會被銷毀,如果有必要執行finalize方法,則會將該對象放入F-Queue隊列,會進行第二次標記,如果他們在此期間與一個對象向連接,則不會被回收

      • GCRoot:

        • Java虛擬機棧中引用的對象

        • 方法區中類的靜態屬性引用的對象

        • 方法區中常量引用的對象

        • 本地方法棧JNI引用的對象(JNI 調用其他的語言 如C,C++ 使用方式 native)

    • 停止-復制算法:

      • 將內存分為相等的兩塊 每次使用其中的一塊,回收垃圾時將這一塊上存活的對象放到另一塊上面,然後清理這一塊(效率不高,產生內存碎片)
    • 分帶收集

      • 分為年輕帶(Eden,Survivo1,Survivo2),老年代(Tenured)

      • 一開始對象都放在Eden區域,當新對象生成並且Eden申請空間失敗時,會觸發minor gc,對Eden區域進行GC,清除非存活對象,並且把存活的對象都移動到Survivo1內,然後整理Survivo兩個內存區,在這裏進行的GC不會影響到老年代,所以Eden區的GC會頻繁進行。因而,一般在這裏需要使用速度快、效率高的算法,使Eden區能盡快空閑出來。同時每個對象都有一個年齡,就是經歷過minor gc的次數,當一個對象的年齡到了一定的限制的時候會把這個對象移動到老年區,當老年區的空間沒有的時候就會觸發老年區的的垃圾回收處理

    • 垃圾回收常用的分配方式:指針碰撞,空閑列表

  • Class文件的內容

    • 每個class文件的前4個自己為標識是否能被虛擬機接受

    • 接著為版本號(5 6 字節為次版本號 7 8 為主版本)

    • 接著主版本號的為常量池的入口

    • 訪問標誌

    • 索引(類索引,父類索引,接口索引)

    • 字段表

    • 方法表

    • 屬性表

網絡編程

  • tcp如何保證可靠性

    • 將數據分割為tcp認為適合發送的數據塊

    • 超時重傳:當tcp發出一個數據段後,會啟動一個定時器,等待目的端確認收取這個報文,在一定時間內若不能及時收到一個確認,則會重新發送一個報文段。

    • 當tcp收到一個報文段的時候會給對方發送一個確定,這個確認通常不是立即發送,通常推遲幾分之1秒

    • 當tcp收到報文段但報文段有錯誤的時候將會丟棄報文段,並且不給出響應

    • 對於失序的數據進行重新排序然後交給應用層

    • 對於重復的數據,直接丟棄

    • tcp可以進行流量的控制,防止主機較快的一方傳輸數據過快導致主機較慢的一方緩存區溢出

  • 字節流服務

    • 兩個應用程序通過字節流相連接,tcp不在字節流中插入記錄標識符
  • TCP 和 UDP——tcp:面向連接,提供可靠的服務,無重復、無丟失、無差錯,面向字節流,只能是點對點,首部 20 字節,全雙工。 UDP:無連接,盡最大努力交付,面向報文,支持一對一、一對多、多對多,首部 8 字節

  • https: http+ssl/tls,在http上又添加了一層處理加密信息的模塊,服務端和客戶端的傳輸都會進行加密。

    • 客戶端發出https請求

    • 服務端配置

    • 傳輸證書

    • 客戶端解析證書(生成一個隨機值並且用公鑰對其加密)

    • 傳輸加密信息(傳輸的為加密後的隨機值)

    • 服務端解密信息(用對稱加密的算法解析傳遞過來的請求)

    • 傳輸加密的相應

    • 客戶端解密(客戶端抓包為明文)

  • 反向代理和正向代理

    • 正向代理:連接一個代理服務器讓他幫助我們訪問目標網站,目標網站並不知道Client是誰,

      • 訪問訪問不了的網站

      • 可以加速訪問資源

      • 對外隱藏客戶信息

    • 反向代理:客戶端請求Server的時候不知道Server返回的數據從什麽地方來的,代理將請求分發到不同的服務器上

      • 負載均衡

      • 保證內網安全

  • nginx設置反向代理的五種方法

    • 輪詢(默認),每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器 down 掉,能自動剔除;

    • 指定權重,指定輪詢幾率。權重越大,輪詢幾率越大,用於後端服務器性能不均的情況。

    • ip 綁定 ip_path,每個請求按訪問 ip 的哈希結果分配,這樣每個客戶固定訪問一個服務器,可以解決 session 問題。

    • fair(第三方)按後端服務器的響應時間來分配請求,響應時間短的優先分配。

    • url_hash 按訪問的 url 結果來分配請求,使每個 url 定位到同一個後端服務器。

  • webService:是一種跨編程語言和跨操作系統的遠程調用技術,就是說服務器采用java編寫,客戶端程序可以采用其他編程語言編寫,且客戶端和服務器程序可以在不同操作系統上運行。

算法和數據結構

  • 堆排序的空間復雜度(O(1)建堆的時間復雜度(O(n)) 調整堆的時間復雜度(O(logn))

  • 哈弗曼樹有左右子樹之分

  • 稀疏矩陣,三元組存儲: 非零元素所在的行以及所在的列和他的值構成一個三元組,然後按照某種順序存放三元組,還需三個變量來記錄表矩陣額行數,列數和總的元素數量

  • BFS:廣度優先遍歷,使用隊列

  • DFS:深度優先遍歷,使用棧

  • 快速排序在無序是效率高,有序時效率低

  • 知道中序,再知道前序或者後序一個就可以構建一個二叉樹

  • 對冒泡排序的改進是加入一個標誌位,標誌這一次排序是否有數據交換,如果進行某一趟沒有數據交換,代表已經排好序

Java面試基本知識