最近,春招已經基本接近尾聲了,我找了幾位拿到名企Offer的小夥伴,請他們總結了面試經驗,近期會分批的推送給你們。但願給那些正在準備秋招的同窗提供些幫助。這是一篇7000字的長文,總結了本身參加京東校招並拿到offer的面試題及答案,還有學習方法。對於一個校招生來講,能把JVM、網絡知識、JDK源碼等了解的這麼全面,他不進京東,誰進京東。作到他這樣,你,也能夠。java
面試時間較長,回答速度也較快,全部問題都進行了完整的回答。形式爲電話面試,都是基礎,難度通常,沒關係張,回答知識點便可。linux
內容主要包括jvm相關,網絡知識(TCP/IP,DNS),JDK源碼(HashMap, ArrayList, HashTable等)nginx
這部分主要考的是知識點的串聯能力,面試官提出一個問題時,要把該問題相關的知識點都羅列出來(在說以前能夠詢問面試官是否須要詳細講述該知識點)。面試
參考書籍:深刻理解Java虛擬機-周志明 神書!神書!神書!建議多刷幾遍,書中的全部知識點能夠經過JAVA運行時區域和JAVA的內存模型與線程兩個大模塊羅列徹底。redis
常考內容有:GC,JAVA線程實現方式,volatile底層原理,線程安全,鎖與CAS等算法
1. 講下JAVA的運行時區域spring
回答:運行時數據區總體分爲兩類 線程私有和線程共享。sql
線程私有的包括:數據庫
程序計數器數組
若正在執行的是java方法,則計數器記錄的是正在執行的字節碼指令的地址
若正在執行的是native方法,則計數器爲空
該區域是惟一一個不會致使outofmemoryError的區域
虛擬機棧
描述的是Java方法執行的內存模型:每一個方法都會建立一個棧幀用於存儲局部變量表,操做數棧,動態連接,方法出口等信息
局部變量表存放了編譯期可知的基本數據類型,對象引用,和returnAddress類型(指向一條字節碼指令地址),局部變量表的內存空間在編譯器肯定,在運行期不變
可致使兩種異常:線程請求的棧深度大於虛擬機容許的深度-StackOverflowError;虛擬機沒法申請到足夠的內存-OutOfMemoryError
本地方法棧
和虛擬機棧相似,但它是爲Native方法服務的
線程共享的包括:
堆
java堆是被全部線程共享的內存區域,在虛擬機啓動時建立,用來分配對象實例和數組
堆是垃圾回收器主要管理的區域,堆可分爲新生代和老年代
從內存分配角度看,堆可劃分出多個線程私有的分配緩衝區(TLAB)
大小可經過 -Xmx 和 -Xms 控制
方法區
用來存放虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等信息
GC會回收該區域的常量池和進行類型的卸載 *運行時常量池
Class文件的常量池用於存放編譯期生成的各類字面量和符號引用,這部份內容將在類加載後存放在運行時常量池中
還把翻譯出來的直接引用也放在運行時常量池中,運行時產生的常量也放在裏面
2. 簡單說下垃圾回收機制
大體思路: 要進行垃圾回收,首先要判斷一個對象是否活着,這就引出了兩種方法…
引用計數法和可達性分析法
gc roots 類型
引用類型
兩次標記過程
垃圾回收算法
內存分配策略
觸發垃圾回收
垃圾回收器
也會回收方法區
回答:要進行垃圾回收,首先要判斷對象是否存活,引出了兩個方法:
引用計數法
思想:給對象設置引用計數器,沒引用該對象一次,計數器就+1,引用失效時,計數器就-1,當任意時候引用計數器的值都爲0時,則該對象可被回收
Java不適用緣由:沒法解決對象互相循環引用的問題
可達性分析法
虛擬機棧(棧幀中的局部變量表)中引用的對象
方法區中類靜態屬性引用的對象
方法區中常量引用的對象
本地方法棧中JNI(Native方法)引用的對象
以GC Roots爲起點,從這些起點開始向下搜索,通過的路徑稱爲引用鏈。若一個對象到GC Roots之間沒有任何引用鏈,則該對象是不可達的。
那麼可做爲GC Roots的對象有
在可達性分析過程當中,對象引用類型會對對象的生命週期產生影響,JAVA中有這幾種類型的引用:
強引用:只要該引用還有效,GC就不會回收
軟引用:內存空間足夠時不進行回收,在內存溢出發生前進行回收、用SoftReference類實現
弱引用:弱引用關聯的對象只能存活到下一次Gc收集、用WeakReference類實現
虛引用:沒法經過虛引用得到對象實例,也不會對對象的生存時間產生影響、惟一目的:當該對象被Gc收集時,收到一個系統通知。用PhantomReference類實現
一個對象真正不可用,要經歷兩次標記過程:
首先進行可達性分析,篩選出與GC Roots沒用引用鏈的對象,進行第一次標記
第一次標記後,再進行一次篩選,篩選條件是是否有必要執行finalize()方法。若對象有沒有重寫finalize()方法,或者finalize()是否已被jvm調用過,則不必執行,GC會回收該對象
如有必要執行,則該對象會被放入F-Queue中,由jvm開啓一個低優先級的線程去執行它(但不必定等待finalize執行完畢)。
Finalize()是對象最後一次自救的機會,若對象在finalize()中從新加入到引用鏈中,則它會被移出要回收的對象的集合。其餘對象則會被第二次標記,進行回收
JAVA中的垃圾回收算法有:
標記-清除(Mark-Sweep)
兩個階段:標記, 清除
缺點:兩個階段的效率都不高;容易產生大量的內存碎片
複製(Copying)
把內存分紅大小相同的兩塊,當一塊的內存用完了,就把可用對象複製到另外一塊上,將使用過的一塊一次性清理掉
缺點:浪費了一半內存
標記-整理(Mark-Compact)
標記後,讓全部存活的對象移到一端,而後直接清理掉端邊界之外的內存
分代收集
把堆分爲新生代和老年代
新生代使用複製算法
將新生代內存分爲一塊大的Eden區和兩塊小的Survivor;每次使用Eden和一個Survivor,回收時將Eden和Survivor存活的對象複製到另外一個Survivor(HotSpot的比例Eden:Survivor = 8:1)
老年代使用標記-清理或者標記-整理
觸發GC又涉及到了內存分配規則: (對象主要分配在Eden,若啓動了本地線程分配緩衝,將優先在TLAB上分配)
對象優先在Eden分配
當Eden區沒有足夠的空間時就會發起一次Minor GC
大對象直接進入老年代
典型的大對象是很長的字符串和數組
長期存活的對象進入老年代
每一個對象有年齡計數器,每通過一次GC,計數器值加一,當到達必定程度時(默認15),就會進入老年代
年齡的閾值可經過參數 -XX:MaxTenuringThreshold設置
對象年齡的斷定
Survivor空間中相同年齡全部對象大小的總和大於Survivor空間的一半,年齡大於等於該年齡的對象就可直接進入老年代,無須等到MaxTenuringThreshold要求的年齡
空間分配擔保
發生Minor GC前,jvm會檢查老年代最大可用的連續空間是否大於新生代全部對象總空間,若大於,則Minor GC是安全的
若不大於,jvm會查看HandlePromotionFailure是否容許擔保失敗,若不容許,則改成一次Full GC
若容許擔保失敗,則檢查老年代最大可用的連續空間是否大於歷次晉升到老年代對象的平均大小,若大於,則嘗試進行Minor GC;若小於,則要改成Full GC
垃圾收集器:
Serial(串行收集器)
特性:單線程,stop the world,採用複製算法
應用場景:jvm在Client模式下默認的新生代收集器
優勢:簡單高效
ParNew
特色:是Serial的多線程版本,採用複製算法
應用場景:在Server模式下經常使用的新生代收集器,可與CMS配合工做
Parallel Scavenge
特色:並行的多線程收集器,採用複製算法,吞吐量優先,有自適應調節策略
應用場景:須要吞吐量大的時候
SerialOld
特色:Serial的老年代版本,單線程,使用標記-整理算法
Parallel Old
Parallel Scavenge的老年代版本,多線程,標記-整理算法
CMS
對CPU資源敏感
沒法處理浮動垃圾(併發清除 時,用戶線程仍在運行,此時產生的垃圾爲浮動垃圾)
產生大量的空間碎片
初始標記:stop the world 標記GC Roots能直接關聯到的對象
併發標記:進行GC Roots Tracing
從新標記:stop the world;修正併發標記期間因用戶程序繼續運做而致使標記產生變更的 那一部分對象的標記記錄
併發清除:清除對象
特色:以最短回收停頓時間爲目標,使用標記-清除算法
過程:
優勢:併發收集,低停頓
缺點:
G1
初始標記:stop the world 標記GC Roots能直接關聯到的對象
併發標記:可達性分析
最終標記:修正在併發標記期間因用戶程序繼續運做而致使標記產生變更的那一部分標記記錄
篩選回收:篩選回收階段首先對各個Region的回收價值和成本進行排序,根據用戶所指望的GC停頓時間來制定回收計劃
並行與併發
分代收集
空間整合:從總體看是基於「標記-整理」的,從局部(兩個region之間)看是基於「複製」的。
可預測的停頓:使用者可明確指定在一個長度爲M毫秒的時間片斷內,消耗在垃圾收集上的時間不得超過N毫秒。
特色:面向服務端應用,將整個堆劃分爲大小相同的region。
執行過程:
GC自適應調節策略 Parallel Scavenge收集器有一個參數-XX:+UseAdaptiveSizePolicy。當這個參數打開以後,就不須要手工指定新生代的大小、Eden與Survivor區的比例、晉升老年代對象年齡等細節參數了,虛擬機會根據當前系統的運行狀況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或者最大的吞吐量,這種調節方式稱爲GC自適應的調節策略(GC Ergonomics)。
(垃圾回收器部分重點講CMS和G1)
最後提一下也會回收方法區:
永久代中主要回收兩部份內容:廢棄常量和無用的類
廢棄常量回收和對象的回收相似
無用的類需知足3個條件
該類的全部實例對象已被回收
加載該類的ClassLoader已被回收
該類的Class對象沒有在任何地方被引用,沒法在任何地方經過反射訪問該類的方法
上面的知識點在你多刷幾遍書,腦中造成相應的知識網後能很全面的說出來。
網絡知識在面試中很是重要,尤爲是TCP,DNS,HTTP等知識點。
該部分個人蔘考書籍是:圖解HTTP,圖解TCP/IP(對於開發來講,這兩本書在網絡方面的講解應該夠用了),以及相關博客。
回答該類問題時,依然要從面試官提到的問題進行擴散,把相關的問題本身拋出來進行講述(在拋出講述時能夠詢問面試官是否須要進行詳細的講解)
1. 講一下TCP三次握手
對於該問題,能夠直接關聯TCP四次分手進行回答。如果當場面試,能夠在紙上畫出客戶端和服務端的TCP狀態序列
而後本身能夠拋出相關的問題進行回答,如:
爲何不採用兩次握手,SYN半鏈接攻擊,TIMEWAIT數量太多怎麼辦,爲何鏈接的時候是3次握手,關閉的時候是4次分手,爲何TIMEWAIT狀態須要通過2MSL(最大報文段生存時間)才能回到CLOSE狀態等等問題(這些問題在網上都有講解,這裏就不贅述了)。
2. TCP和UDP的區別(很常見的問題):
TCP面向鏈接(如打電話要先撥號創建鏈接) UDP是無鏈接的,即發送數據以前不須要創建鏈接
TCP提供可靠的服務。也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付
TCP面向字節流,其實是TCP把數據當作一連串無結構的字節流;UDP是面向報文的
UDP沒有擁塞控制,所以網絡出現擁塞不會使源主機的發送速率下降(對實時應用頗有用,如IP電話,實時視頻會議等)
每一條TCP鏈接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通訊
TCP首部開銷20字節;UDP的首部開銷小,只有8個字節
TCP的邏輯通訊信道是全雙工的可靠信道,UDP則是不可靠信道
3. 講下ARP原理
根據目標Ip地址藉助ARP請求和ARP響應來肯定目標的MAC地址
原理:經過廣播發送ARP請求,Ip地址一致的主機接收該請求,而後將本身的MAC地址加入的ARP響應包返回給源主機。要進行MAC地址緩存來避免佔用網絡流量
每一個主機都會在本身的ARP緩衝區創建一個ARP列表,表示Ip地址和MAC地址的對應關係
當源主機要發送數據時,首先檢查ARP列表中是否有對應Ip地址的目標主機的MAC地址,如有,則直接發送,若無,則向本網段的全部主機發送ARP數據包,該數據包包括的內容有:源Ip地址,源MAC地址,目標主機Ip地址
當本網絡的全部主機收到該ARP數據包時,首先檢查書包中的Ip地址是不是本身的Ip地址,若不是則丟棄,如果,則首先從數據包中取出源主機的IP和MAC地址寫入本身的ARP列表中,若已存在,則覆蓋;而後將本身的MAC地址寫入ARP響應包中,告訴源主機本身的MAC地址
源主機收到ARP響應包後,將目標主機的IP和MAC地址寫入ARP列表中。若源主機一直沒有收到ARP響應,則ARP查詢失敗
(廣播發送ARP請求,單播發送ARP響應) 此時,本身能夠加上ARP攻擊及免費ARP相關知識點(可自行搜索)
這部分主要在於本身平時的積累,能夠跟着相關的博客看源碼。常考的內容有String,集合框架,foreach(Iterator及fail-fast機制)等內容。
1. HashMap瞭解嗎,說一下
這裏就不詳細說了,大體思路是jdk7和jdk8的實現原理及區別(重點有實現的數據結構,存儲單元從Entry到Node的轉變,加載因子,何時擴容,jdk1.8擴容的具體實現方式等等),HashMap和HashTable的區別,HahsMap和HashSet的關係。要結合源碼說。
ArrayList瞭解嗎,說一下
重點是底層實現方式,擴容機制,以及LinkedList的底層實現方式;它們之間的區別。要結合源碼說
面試時間不長,個別問題回答的有些底虛。主要考察的是知識面的廣度和對技術的熱愛程度,以及對作過項目的熟悉程度。仍是那句話,坦誠地回答問題,不會就是不會,若是僞裝會可是被接下來地問題問倒的話,那就沒戲了。
實習時項目的相關問題
每一個人的項目都不一樣,只列舉幾個問題
項目是怎樣預防sql注入的
回答:用的是mybatis,sql語句中用#{},#{}表示一個佔位符號,經過#{}能夠實現preparedStatement向佔位符中設置值,jdbc有個預編譯的過程能夠有效預防sql注入,儘可能不用${},它是個拼接符,用來拼接sql字符串。
項目中你作到的redis緩存相關的切面配置(簡歷中有寫)
切面分析:@Aspect
切面: 查詢前先查詢redis,若查詢不到,則查數據庫,獲得數據後存到redis中
目標方法:查詢數據庫
前置:查詢以前先查redis
後置:從數據庫中查到的內容放到redis中
切面中的通知定位環繞通知:@Around
而後又問了aop的實現原理(jdk動態代理和cglib字節碼加強,在回答時要說出底層源碼)
喜歡什麼技術
答:分佈式,實習時雖然本身作的是企業後臺,並無涉及到不少分佈式的內容,可是會常常從同事那裏瞭解一些分佈式的技術感受頗有趣
都瞭解到了哪些分佈式的技術
答:進行反向代理和負載均衡的nginx,及實現高可用的keepalived+nginx;內存數據庫redis及它的基本數據類型和持久化方式;用於作註冊中心的zookeeper和服務治理的dubbo;防止用戶重複登陸的單點登陸;分佈式的文件存儲系統fastdfs;頁面靜態化處理的freemarker;以及用於搜索的solr(這部分因爲有些技術本身只是會用,不瞭解底層,因此說的吞吞吐吐,很沒底氣,其實不必,大大方方說出來後再說明本身瞭解的程度便可)
感受本身哪方面有欠缺
答:spring源碼不太瞭解,另外linux方面有些薄弱,正在補充相關知識。(能夠加上本身目前正在看哪些書)
jdk9有哪些認識
答:不太清楚,還沒了解(心裏狀態:臥槽,jdk9何時出來的) (這個問題能夠很好的瞭解到求職者對技術的熱愛程度,平時能夠多關注技術的發展方向,版本迭代。這方面能夠經過關注一些優質的公衆號:如Java技術zhai)
爲何想來互聯網公司
答:多是第一份實習工做的影響吧, 面試官:還有呢? 我:我也說不清楚,就是想去互聯網公司(說完以後就想宰了本身)
hr面重要的也是真誠,還有就是表達好本身想去該公司及對該公司的瞭解
目前有幾個offer
答:1個,可是已經拒了
爲何拒了
答:由於它不是互聯網公司
你爲何想在互聯網公司發展
答:工資高是一方面,另外在互聯網公司中通常能夠更快接觸到新的技術
爲何想來京東
答:由於京東是我關注好久的公司,從京東第一次作秋招視頻直播就開始關注了。首先京東是一家互聯網公司,其次京東近些年的發展有目共睹,並且京東正在向技術公司轉型,相信本身能夠學到不少東西。
你有什麼缺點
答:壓力大時喜歡經過吃東西來排解壓力,因此又要減肥什麼的很麻煩
還有呢
答:喜歡熬夜
還有呢
答:emmmm,哎呀,想不起來了 (其實,關於優勢和缺點的問題應該好好總結一下,否則問的當時容易懵逼) 還有幾個問題不太記得了,大概就是實習時本身意見和同事不同時是怎麼解決的。對於這種問題,最好舉個實際的例子。
想要了解更多面試經驗及面試題的,能夠關注我一下,另外順便給你們推薦一個交流學習羣:650385180,裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化這些成爲架構師必備的知識體系。還能領取免費的學習資源,目前受益良多,如下的課程體系圖也是在羣裏獲取。
其實網上的大多數面經已經說的很清楚,必定要造成本身的知識樹,若是僅僅想經過看面經來經過面試,會很難。本身日常必定要積累知識,把知識點分類進行記錄,在面試過程當中主動說出面試官所提問題的關聯問題的解決方案可以加分,體現本身的知識串聯能力。關於要積累哪些知識,能夠參考上面的建議。