區塊鏈或後端方面面經
1. 執行緒棧:先是會自動擴充套件,到達最大值才會溢位,溢位之後程式會收到一個段錯誤(java表現為異常),調高堆疊容量可能會增加記憶體開銷和啟動時間
2. 堆和棧的區別:(總結,棧的一切由系統管理,所以堆有各種碎片問題)
• 管理方式:棧由編譯器自動管理;堆由程式設計師控制,使用方便,但易產生記憶體洩露。
• 生長方向:棧向低地址擴充套件(即”向下生長”),是連續的記憶體區域;堆向高地址擴充套件(即”向上生長”),是不連續的記憶體區域。這是由於系統用連結串列來儲存空閒記憶體地址,自然不連續,而連結串列從低地址向高地址遍歷。
• 空間大小:棧頂地址和棧的最大容量由系統預先規定(通常預設2M或10M);堆的大小則受限於計算機系統中有效的虛擬記憶體,32位Linux系統中堆記憶體可達2.9G空間。
• 儲存內容:棧用於函式呼叫等,堆的內容由程式設計師決定。
• 分配方式:棧可靜態分配或動態分配。靜態分配由編譯器完成,如區域性變數的分配。動態分配由alloca函式在棧上申請空間,用完後自動釋放。堆只能動態分配且手工釋放。
• 分配效率:棧由計算機底層提供支援:分配專門的暫存器存放棧地址,壓棧出棧由專門的指令執行,因此效率較高。堆由函式庫提供,機制複雜,效率比棧低得多。Windows系統中VirtualAlloc可直接在程序地址空間中分配一塊記憶體,快速且靈活。
• 分配後系統響應:只要棧剩餘空間大於所申請空間,系統將為程式提供記憶體,否則報告異常提示棧溢位。
• 碎片問題:棧不會存在碎片問題,因為棧是先進後出的佇列,記憶體塊彈出棧之前,在其上面的後進的棧內容已彈出。而頻繁申請釋放操作會造成堆記憶體空間的不連續,從而造成大量碎片,使程式效率降低。
2. linux中有幾種棧:程序棧、執行緒棧、核心棧( 在執行系統呼叫陷入核心之後,這些核心程式碼所使用的棧並不是原先程序使用者空間中的棧,而是一個單獨核心空間的棧,這個稱作程序核心棧)、中斷棧
3. 類載入過程:載入、連線(驗證、準備、解析)、初始化、使用、解除安裝
4. 什麼時候需要類載入:new、反射、發現父類未初始化、主類、動態語言支援(注意,被動引用不觸發初始化,如陣列引用,通過子類引用父類)
5. synchronized和lock的區別
• synchronized:可以只對需要同步的使用與wait()/notify()/nitifyAll()一起使用時,比較方便
• lock:可控性更好,在併發量比較小的情況下,使用synchronized是個不錯的選擇,但是在併發量比較高的情況下,其效能下降很嚴重,此時ReentrantLock是個不錯的方案。
6. synchronized鎖:
• Synchronized修飾非靜態方法,實際上是對呼叫該方法的物件加鎖,俗稱“物件鎖”。
• Synchronized修飾靜態方法,實際上是對該類物件加鎖,俗稱“類鎖”
11. java實現計數器:原子操作類、加鎖
13. sql語句:
• select * from TableA left join TableB on TableA.id=TableB.id 左外連線
• select * from TableA right join TableB on TableA.id=TableB.id 右外連線
• select * from TableA full join TableB on TableA.id=TableB.id 全外連線
全連線:完整外部聯接返回左表和右表中的所有行。當某行在另一個表中沒有匹配行時,則另一個表的選擇列表列包含空值。如果表之間有匹配行,則整個結果集行包含基表的資料值。
• select * from TableA JOIN TableB on TableA.id=TableB.id 內連線
自然連線:在連線條件中使用等於(=)運算子比較被連線列的列值,但它使用選擇列表指出查詢結果集合中所包括的列,並刪除連線表中的重複列。
• select * from TableA cross join TableB 交叉連線
交叉連線:交叉聯接返回左表中的所有行,左表中的每一行與右表中的所有行組合。交叉聯接也稱作笛卡爾積。
14. 目錄樹資料庫表設計:用一個一級分類表,一個二級表,用父節點id表示。本質上是一個一對多的關係,可以借鑑下面這個表:
l ID 編號 int
l aDept_DeptID 部門程式碼 char
l aDept_DeptName 部門名稱 char
15. 長連線怎麼實現:
16. 什麼時候選擇innodb、myisam:前者支援更多功能,如行級鎖,後者效率更高,節省儲存
17. hashmap和hashtable的區別:能不能接受null,執行緒安全,快速失敗迭代,擴容方式
18. 資料庫索引什麼時候會失效:
1、索引列有函式處理或隱式轉換,不走索引 2、索引列傾斜,個別值查詢時,走索引代價比走全表掃描高,所以不走索引 3、索引列沒有限制 not null,索引不儲存空值,如果不限制索引列是not null,oracle會認為索引列有可能存在空值,所以不會按照索引計算)
19. java如何實現不可變類:
• 所有成員都是 private final 的
• 不提供對成員的改變方法,例如:setXXXX
• 確保所有的方法不會被過載。手段有兩種:使用final Class(強不可變類),或者將所有類方法加上final(弱不可變類)。
• 如果某一個類成員不是基本型別(primitive type)或不可變類,必須通過在成員初始化(in)或者getter方法(out)時通過深度拷貝(即複製一個該類的新例項而非引用)方法,來確保類的不可變。
• 如果有必要,重寫hashCode和equals方法,同時應保證兩個用equals方法判斷為相等的物件,其hashCode也應相等。
20. reactor和proactor有什麼區別:
21. 如何設計無鎖資料結構:CAS、自旋鎖
22. jdk1.8中對hashMap的優化:
23. 不可變類的優點:
• 只有當字串是不可變的,字串池才有可能實現。字串池的實現可以在執行時節約很多heap空間,因為不同的字串變數都指向池中的同一個字串。但如果字串是可變的,那麼String interning將不能實現(譯者注:String interning是指對不同的字串僅僅只儲存一個,即不會儲存多個相同的字串。),因為這樣的話,如果變數改變了它的值,那麼其它指向這個值的變數的值也會一起改變。
• 如果字串是可變的,那麼會引起很嚴重的安全問題。譬如,資料庫的使用者名稱、密碼都是以字串的形式傳入來獲得資料庫的連線,或者在socket程式設計中,主機名和埠都是以字串的形式傳入。因為字串是不可變的,所以它的值是不可改變的,否則黑客們可以鑽到空子,改變字串指向的物件的值,造成安全漏洞。
• 因為字串是不可變的,所以是多執行緒安全的,同一個字串例項可以被多個執行緒共享。這樣便不用因為執行緒安全問題而使用同步。字串自己便是執行緒安全的。
• 類載入器要用到字串,不可變性提供了安全性,以便正確的類被載入。譬如你想載入java.sql.Connection類,而這個值被改成了myhacked.Connection,那麼會對你的資料庫造成不可知的破壞。
• 因為字串是不可變的,所以在它建立的時候hashcode就被快取了,不需要重新計算。這就使得字串很適合作為Map中的鍵,字串的處理速度要快過其它的鍵物件。這就是HashMap中的鍵往往都使用字串。
24. 怎麼實現一個不可變類:
• 將類宣告為final,所以它不能被繼承
• 將所有的成員宣告為私有的,這樣就不允許直接訪問這些成員
• 對變數不要提供setter方法
• 將所有可變的成員宣告為final,這樣只能對它們賦值一次
• 通過構造器初始化所有成員,進行深拷貝(deep copy)
• 在getter方法中,不要直接返回物件本身,而是克隆物件,並返回物件的拷貝
25. 記憶體洩露的可能原因:
• 靜態集合類引起記憶體洩漏:
• 當集合裡面的物件屬性被修改後,再呼叫remove()方法時不起作用。(key被修改,hashcode發生了改變)
• 監聽器
• 資料庫連線等
• 內部類和外部模組的引用
• 單例模式
26. 資料庫索引有哪些
• 唯一索引/非唯一索引
• 主鍵索引(主索引)(有約束,但是索引沒有)
• 聚集索引/非聚集索引
• 組合索引
27. 序列化原理
l (1)將物件例項相關的類元資料輸出。
l (2)遞迴地輸出類的超類描述直到不再有超類。
l (3)類元資料完了以後,開始從最頂層的超類開始輸出物件例項的實際資料值。
l (4)從上至下遞迴輸出例項的資料
28. 如何實現equal
l 將顯示引數命名為otherObject,稍後轉化為目標型別並命名為other;
l 檢查this和otherObject是否相同;
l 檢查otherObject是否為空,為空則返回false;
l 檢查this和otherObject型別是否相同;
l 將otherObject轉化為目標型別,並命名為other;
l 對型別中定義的屬性進行比較,如果是基礎資料型別使用==,如果是引用型別使用equals()。
29. java的基本資料型別:8位:Byte(位元組型) 16位:short(短整型)、char(字元型) 32位:int(整型)、float(單精度型/浮點型) 64位:long(長整型)、double(雙精度型) 最後一個:boolean(布林型別)
1.7中,永久代仍存在於JDK1.7中,並沒完全移除,譬如符號引用(Symbols)轉移到了native heap;字面量(interned strings)轉移到了java heap;類的靜態變數(class statics)轉移到了java heap。
31. java泛型的理解,以及和c++的不同
l C++模板可以使用int等基本資料型別。Java則不行,必須轉而使用Integer
l Java中,可以將模板的型別引數限定為某種特定型別。例如,你可能會使用泛型實現CardDeck,並規定引數必須擴充套件自CardGame。
l C++中,型別引數可以例項化,Java不可以例項化
l Java中,型別引數(即MyClass<Foo>中的Foo)不能用於靜態方法和變數,因為他們會被MyClass<Foo>和MyClass<Bar>共享。但在C++中,這些類是不同的,型別引數可以用於靜態方法和靜態變數。
l 在Java中,不管型別引數是什麼,MyClass的所有例項都是同一型別。型別引數會在執行時被抹去。而C++中,引數型別不同,例項型別也不同
33. 介面和抽象類的區別
l 介面的修飾符可以為public和default。將介面定義成protected和private是沒有意義的,而且編譯器也不允許這麼做
l 介面可以extends介面,但是介面不能繼承或者實現抽象類
l 介面中的變數預設都會被final修飾為常量,亦可以加static修飾符將其定義成靜態常量,
l 介面中的變數由於是常量,須在定義介面的時候就為其初始化
l 介面方法的修飾符有public abstract均為預設修飾
l 關於介面中方法的實現:並不所有的子類都必須實現介面的方法,當子類是抽象類的時候,可以不實現介面中的方法
36. java exception型別:
l 1、Error
l 2、Runtime Exception 執行時異常
l 3、Exception
l 4、throw 使用者自定義異常
37. HashMap什麼情況下發生死鏈:併發環境下,hash衝突之後的互指
38. 索引一定有效嗎?失效的情況?索引是怎麼實現的?
l 隱式轉換導致索引失效.
l 對索引列進行運算導致索引失效
l 使用Oracle內部函式導致索引失效
l a. 使用 <> 、not in 、not exist、!=
l b. like "%_" 百分號在前(可採用在建立索引時用reverse(columnName)這種方法處理)
39. 如果你的專案資料量大100倍,1000倍的話,資料庫要怎麼進行改進?(分庫分表,然而我就知道分庫分表並不知道怎麼做。。)
40. 面向物件的原則
• 1. 單一職責原則(Single Responsibility Principle)每一個類應該專注於做一件事情。
• 2. 里氏替換原則(Liskov Substitution Principle)超類存在的地方,子類是可以替換的。
• 3. 依賴倒置原則(Dependence Inversion Principle)實現儘量依賴抽象,不依賴具體實現。
• 4. 介面隔離原則(Interface Segregation Principle)應當為客戶端提供儘可能小的單獨的介面,而不是提供大的總的介面。
• 5. 迪米特法則(Law Of Demeter)又叫最少知識原則,一個軟體實體應當儘可能少的與其他實體發生相互作用。
• 6. 開閉原則(Open Close Principle)面向擴充套件開放,面向修改關閉。
• 7. 組合/聚合複用原則(Composite/Aggregate Reuse Principle CARP)儘量使用合成/聚合達到複用,儘量少用繼承。原則: 一個類中有另一個類的物件。
41. ArrayList的sublist修改是否影響list本身:會,如果有擴容,父list會導致子list失效,子list會對映到父list
42. 分別介紹一下NIO,AIO,BIO
43. countdownLatch的底層實現:佇列同步器
44. mysql鎖:
l 行鎖(Record Lock):鎖直接加在索引記錄上面。
l 間隙鎖(Gap Lock):鎖加在不存在的空閒空間,可以是兩個索引記錄之間,也可能是第一個索引記錄之前或最後一個索引之後的空間。
l Next-Key Lock:行鎖與間隙鎖組合起來用就叫做Next-Key Lock。
45. tryLock()在什麼場景下用
46. 502和504的區別:
a) 作為閘道器或者代理工作的伺服器嘗試執行請求時,從上游伺服器接收到無效的響應,
b) 作為閘道器或者代理工作的伺服器嘗試執行請求時,未能及時從上游伺服器(URI標識出的伺服器,例如HTTP、FTP、LDAP)或者輔助伺服器(例如DNS)收到響應。
58. 什麼是ack攻擊
a) 軟體開發過程中的流程、敏捷開發的優勢缺點、需求分析與設計
b) OSI七層模型: :物理層、資料鏈路層、網路層、傳輸層、會話層、表示層和應用層。
59. • sql中的連線:內連線、外連線(左、右)、交叉連線。總結(左連線:左邊有的,右邊沒有的為null 右連線:左邊沒有的,右邊有的為null 內連線:顯示左邊右邊共有的)
a) 資料庫事務:ACID特性(原子性,一致性,隔離性,永續性),針對以下三個問題,提供了四種不同的事務隔離級別。
b) 髒讀:讀取了另一個未提交事務中的資料(事務執行了,但是未提交,可能會回滾)
c) 不可重複讀:讀取了前一事務提交的資料,造成讀取前後不同
d) 幻讀:和不可重複度相同,不同的是這個針對一批資料
60. 三級封鎖協議:
a) 1 級封鎖協議是:事務T在修改資料R之前必須先對其加X鎖,直到事務結束才釋放。事務結束包括正常結束(COMMIT)和非正常結束(ROLLBACK)。 1級封鎖協議可防止丟失修改,並保證事務T是可恢復的。在1級封鎖協議中,如果僅僅是讀資料不對其進行修改,是不需要加鎖的,所以它不能保證可重複讀和不 讀"髒"資料。
b) 2級封鎖協議是:1級封鎖協議加上事務T在讀取資料R之前必須先對其加S鎖,讀完後即可釋放S鎖。2級封鎖協議除防止了丟失修改,還可進一步防止讀"髒"資料。
c) 3級封鎖協議是:1級封鎖協議加上事務T在讀取資料R之前必須先對其加S鎖,直到事務結束才釋放。3級封鎖協議除防止了丟失修改和不讀'髒'資料外,還進一步防止了不可重複讀。
61. 兩段鎖協議:在加鎖階段,事務只能加鎖,也可以操作資料,但不能解鎖,直到事務釋放第一個鎖,就進入解鎖階段,此過程中事務只能解鎖,也可以操作資料,不能再加鎖。
62. 方法區裡面存放了什麼,怎麼判斷是否需要收集方法區?答:類資料,方法資料等。例項已被回收,classloader已被回收以及無反射呼叫時可以回收。
63. 哪些可以作為GCRoot?虛擬機器棧引用物件、靜態屬性引用物件、方法區中常量引用的物件、Native方法引用的物件。
64. 紅黑樹
(1) 每個節點或者是黑色,或者是紅色。
(2) 根節點是黑色。
(3) 每個葉子節點是黑色。 [注意:這裡葉子節點,是指為空的葉子節點!]
(4) 如果一個節點是紅色的,則它的子節點必須是黑色的。
(5) 從一個節點到該節點的子孫節點的所有路徑上包含相同數目的黑節點。
65. 程式碼執行的幾個階段?
66. 編譯:預處理(編譯標頭檔案,替換巨集等)、編譯(轉換為組合語言檔案)、彙編(得到機器語言)、連結(連結不同的.o檔案,得到可執行程式)
67. 多型的好處:
a) 應用程式不必為每一個派生類編寫功能呼叫,只需要對抽象基類進行處理即可。大大提高程式的可複用性。//繼承
b) 派生類的功能可以被基類的方法或引用變數所呼叫,這叫向後相容,可以提高可擴充性和可維護性。 //多型的真正作用,
68. 11. 過載和覆蓋
a) 過載方法: 在一個類中用相同的名字建立多個方法(每個方法的引數表不同)
b) 方法覆蓋: 在一個類中建立的方法與父類中方法的名字、 返回型別和引數表相同,覆蓋是針對兩個類說的,而且必須是子類(或孫類,孫孫類等)覆蓋掉父類的方法
69. IO原理:DMA方式從磁碟讀取到記憶體
70. NIO原理:buffer、channel和選擇器(channel監控)
71. hashmap為什麼擴充時2的冪次:程式碼中用到了位運算
72. 執行緒狀態轉換:新建、執行、阻塞、等待、死亡
17. 二叉樹能代替B樹麼:不能,二叉樹有最壞情況,平衡二叉樹維護開銷大
18. 記憶體排程演算法: LRU:最近最少使用(Least Recently Used)、 FIFO:先進先出(First In First Out)、 Clock:時鐘替換演算法(Clock)
19. 資料庫正規化:第一正規化(不可分割)、第二正規化(有主鍵,消除依賴)、第三正規化(消除非主屬性的傳遞依賴)、BCNF(消除主屬性的傳遞依賴)、第四正規化(消除多值依賴)
20. 排序演算法:基於交換、基於插入、堆、歸併等
21. 作業系統主要組成部分:核心、shell、檔案系統、應用程式
22. 作業系統核心的主要工作: 它負責管理系統的程序、記憶體、裝置驅動程式、檔案和網路系統
23. 模組方式載入的優點: 模組本身不編譯進核心,從而控制了核心的大小;模組一旦被載入,將和其它的部分完全一樣。可能產生模組不相容
24. redis資料結構
26. Xmx和Xms設定:記憶體分配,xms是開始垃圾回收值,xmx是最大記憶體
27. full gc日誌格式:時間,停頓型別,區域,回收前後記憶體使用,gc佔用時間
28. java 代理模式:靜態、動態、Cglib代理(見魏世康java基礎)
a) JDK:(代理模式:代理類和目標類實現共同的介面)
73. 代理模式的作用是:為其它物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個客戶不想直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介作用。(分為抽象角色,代理角色和真實角色)
74. 實現InvocationHandler介面來實現一個動態代理類,再使用Proxy.newProxyInstance方法來動態建立一個代理物件的類。
a) CGLIB:(代理類是目標類的子類)
75. JDK的動態代理機制只能代理實現了介面的類,而不能實現介面的類就不能實現JDK的動態代理,cglib是針對類來實現代理的。(動態建立子類)
76. 代理類實現MethodInterceptor介面
77. 優點:CGLib建立的動態代理物件效能比JDK建立的動態代理物件的效能高不少,但是CGLib在建立代理物件時所花費的時間卻比JDK多得多,所以對於單例的物件,因為無需頻繁建立物件,用CGLib合適,反之,使用JDK方式要更為合適一些。同時,由於CGLib由於是採用動態建立子類的方法,對於final方法,無法進行代理。
78. 25. 序列化的實現:
a) 將物件例項相關的類元資料輸出。
b) 遞迴地輸出類的超類描述直到不再有超類。
c) 類元資料完了以後,開始從最頂層的超類開始輸出物件例項的實際資料值。
d) 從上至下遞迴輸出例項的資料
1. 程序和執行緒的區別:
a) 程序是資源分配的最小單位,執行緒是程式執行的最小單位。
b) 程序有自己的獨立地址空間,每啟動一個程序,系統就會為它分配地址空間,建立資料表來維護程式碼段、堆疊段和資料段,這種操作非常昂貴。而執行緒是共享程序中的資料的,使用相同的地址空間,因此CPU切換一個執行緒的花費遠比程序要小很多,同時建立一個執行緒的開銷也比程序要小很多。
c) 執行緒之間的通訊更方便,同一程序下的執行緒共享全域性變數、靜態變數等資料,而程序之間的通訊需要以通訊的方式(IPC)進行。不過如何處理好同步與互斥是編寫多執行緒程式的難點。
d) 但是多程序程式更健壯,多執行緒程式只要有一個執行緒死掉,整個程序也死掉了,而一個程序死掉並不會對另外一個程序造成影響,因為程序有自己獨立的地址空間。
3. 如何開啟一個程序?fork()的優點
e) shell:效率低,需等待子程序返回
f) exec:替換原有程序,不返回原程序,繼承原程序很多特性,效率高
g) fork:複製一個和子程序一模一樣的程序,擁有自己的記憶體空間,需要注意殭屍子程序的問題
4. mySQL裡有2000w資料,redis中只存20w的資料,如何保證redis中的資料都是熱點資料
i. 相關知識:redis 記憶體資料集大小上升到一定大小的時候,就會施行資料淘汰策略(回收策略)。redis 提供 6種資料淘汰策略:
h) volatile-lru:從已設定過期時間的資料集(server.db[i].expires)中挑選最近最少使用的資料淘汰
i) volatile-ttl:從已設定過期時間的資料集(server.db[i].expires)中挑選將要過期的資料淘汰
j) volatile-random:從已設定過期時間的資料集(server.db[i].expires)中任意選擇資料淘汰
k) allkeys-lru:從資料集(server.db[i].dict)中挑選最近最少使用的資料淘汰
l) allkeys-random:從資料集(server.db[i].dict)中任意選擇資料淘汰
m) no-enviction(驅逐):禁止驅逐資料
5. 分散式儲存rocksDB、redis、levelDB
6. tcp udp的區別, socket的使用 :
n) 基於連線與無連線;
o) 對系統資源的要求(TCP較多,UDP少);
p) UDP程式結構較簡單;
q) 流模式與資料報模式 ;
r) TCP保證資料正確性,UDP可能丟包,TCP保證資料順序,UDP不保證。
1. hash和樹的區別:
s) hash查詢較快,但是有最差情況。
t) hash需要提前分配很多地址,而樹不需要,節約記憶體。
u) 樹更適應動態插入,可擴充套件性較強,而hash負載過高需要擴容。
v) 樹比較容易做成有序的。
2. http的伺服器端和客戶端能雙向通訊嗎?可以,推送技術
3. full gc問題怎麼定位?用什麼工具?怎麼定位到哪個執行緒和程序?答:年老代是否被寫滿、持久代是否被寫滿(動態類載入)、有沒有顯示呼叫System.gc()。用工具jmap(jhat)、jstack執行緒快照,用VisualVM視覺化。
4. 單例模式實現:
w) 靜態類+工廠模式
x) 單執行緒可以使用時生成
y) 列舉實現單例
z) 雙重加鎖,併發環境有問題
aa) 靜態內部類:使用時才載入並且保證執行緒安全
5. 怎麼用原生的JDBC訪問資料庫
bb) 載入JDBC驅動程式;
cc) 負責管理JDBC驅動程式的類 DriverManager 會識別載入的驅動程式,用 DriverManager 類的方法 getConnection()來建立一個數據庫連線類的例項物件;
dd) 獲取Connection物件的例項,用Connection物件的方法建立一個 Statement 物件例項,執行標準的SQL語句,對資料庫、表進行相關操作。
ee) 返回的結果用 ResultSet 類來處理。
ff) 出現異常時,對事物進行回滾。
7. CPU使用率100%怎麼分析解決:jps,top,jstack
8. CountDownLatch、CyclicBarrier和 Semaphore:
1. countDownLatch是計數器,初始化一個計數器,每個執行緒執行完減一,await最後被喚醒
2. CycliBarrier同步屏障,n個執行緒到達屏障時同時執行
3. Semaphore訊號量,可控制併發的數量
9. 一致性hash原理,實現負載均衡
10. 為什麼jvm調優經常會將-Xms和-Xmx引數設定成一樣:減少動態調整消耗的資源
1. Get和Post請求
gg) GET 請求:
hh) GET 請求可被快取
ii) GET 請求保留在瀏覽器歷史記錄中
jj) GET 請求可被收藏為書籤
kk) GET 請求不應在處理敏感資料時使用
ll) GET 請求有長度限制
mm)GET 請求只應當用於取回資料
nn) POST 請求 :
oo) POST 請求不會被快取
pp) POST 請求不會保留在瀏覽器歷史記錄中
qq) POST 不能被收藏為書籤
rr) POST 請求對資料長度沒有要求