- 請說一下EJB規范中EJB禁止的操作有哪些?
EJB規范中禁止的操作如下:
不能操作線程和線程API(線程API指非線程對象的方法如notify,wait等);
不能操作awt;
不能實現服務器功能;
不能對靜態屬性存取;
不能使用IO操作直接存取文件系統;
不能加載本地庫;
不能將this作為變量和返回;
不能循環調用。 - EJB包括SessionBean和EntityBean,請說出他們的生命周期以及EJB是如何管理事務的?
SessionBean:Stateless Session Bean 的生命周期是由容器決定的,當客戶機發出請求要建立一個Bean 的實例時,EJB 容器不一定要創建一個新的Bean 的實例供客戶機調用,而是隨便找一個現有的實例提供給客戶機。當客戶機第一次調用一個Stateful Session Bean 時,容器必須立即在服務器中創建一個新的Bean 實例,並關聯到客戶機上,以后此客戶機調用Stateful Session Bean 的方法時容器會把調用分派到與此客戶機相關聯的Bean 實例。
EntityBean:Entity Beans 能存活相對較長的時間,並且狀態是持續的。只要數據庫中的數據存在,Entity beans 就一直存活。而不是按照應用程序或者服務進程來說的。即使EJB 容器崩潰了,Entity beans 也是存活的。Entity Beans 生命周期能夠被容器或者Beans 自己管理。
EJB 通過以下技術管理實務:對象管理組織(OMG)的對象實務服務(OTS),SunMicrosystems 的Transaction Service(JTS)、Java Transaction API(JTA),開發組(X/Open)的XA 接口。 - 如何理解Hibernate的延遲加載機制?在實際應用中,延遲加載與Session關閉的矛盾是如何處理的?
Hibernate的延遲加載就是在讀取的時候不會將數據加載進來,等到使用數據時再加載,使用了虛擬代理機制實現延遲加載。
矛盾處理:
可以選擇關閉延遲加載特性;
在session關閉之前先獲取需要查詢的數據;
使用攔截器或過濾器延長Session的生命周期直到視圖獲得數據。
https://www.cnblogs.com/cathyqq/p/5217375.html
- 請介紹一下集合類內存
參考回答:
一、集合類。 Java中的集合包含多種數據結構,如鏈表、隊列、哈希表等。從類的繼承結構來說,可以分為兩大類,一類是繼承自Collection接口,這類集合包含List、Set和Queue等集合類。另一類是繼承自Map接口,這主要包含了哈希表相關的集合類。
1、List、Set和Queue類的繼承結構圖:綠色的虛線代表實現,綠色實線代表接口之間的繼承,藍色實線代表類之間的繼承。
Collection接口除了實現映射的集合類之外的所有集合類定義了一些方法
List集合類型:描述了一種按位置存儲數據的對象,是有序的。用的比較多List包括ArrayList和LinkedList,這兩者的區別:ArrayList的底層的通過數組實現,所以其隨機訪問的速度比較快,但是對於需要頻繁的增刪的情況,效率就比較低了。而對於LinkedList,底層通過鏈表來實現,所以增刪操作比較容易完成,但是對於隨機訪問的效率比較低。
Queue:一般可以直接使用LinkedList完成,LinkedList繼承自Deque,所以LinkedList具有雙端隊列的功能。PriorityQueue是為每個元素提供一個優先級,優先級高的元素會優先出隊列。
Set:Set與List的主要區別是Set是不允許元素是重復的,而List則可以允許元素是重復的。HashSet和LinkedHashSet的區別在於后者可以保證元素插入集合的元素順序與輸出順序保持一致。而TresSet的區別在於其排序是按照Comparator來進行排序的,默認情況下按照字符的自然順序進行升序排列。
Iterable:Collection類繼承自Iterable,該接口的作用是提供元素遍歷的功能,也就是說所有的集合類(除Map相關的類)都提供元素遍歷的功能。Iterable里面包含了Iterator的迭代器。
2、Map類型的集合:最大的優點在於其查找效率比較高,理想情況下可以實現O(1)的時間復雜度。Map中最常用的是HashMap,LinkedHashMap與HashMap的區別在於前者能夠保證插入集合的元素順序與輸出順序一致。這兩者與TreeMap的區別在於TreeMap是根據鍵值進行排序的,其底層的實現也有本質的區別,HashMap底層是一個哈希表,而TreeMap的底層數據結構是一棵樹。
二、Java內存區域划分
1.程序計數器: 可以看做是當前線程所執行的字節碼的行號指示器。在JVM的概念模型里,字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令。 每條線程都有一個獨立的程序計數器,所以程序計數器是線程私有的內存區域。 如果線程執行的是一個Java方法,計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果線程執行的是一個Native方法,計數器的值為空。 Java虛擬機規范中唯一一個沒有規定任何OutOfMemoryError情況的區域。
2.Java虛擬機棧: 描述Java方法執行的內存模型,每個方法執行的同時會創建一個棧幀,棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。Java虛擬機棧是線程私有的,它的生命周期與線程相同。 局部變量表存放了編譯時期可知的各種基本數據類型和對象引用。局部變量表所需的內存空間在編譯時期完成分配,當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。 Java虛擬機規范對這個區域規定了兩種異常情況: 如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常; 如果虛擬機棧可以動態擴展,如果擴展時無法申請到足夠的內存,就會拋出OutOfMemoryError異常;
3.本地方法棧: 本地方法棧與虛擬機棧的區別:虛擬機棧為虛擬機執行Java方法服務(也就是字節碼),而本地方法棧為虛擬機使用到的Native方法服務。 Java虛擬機規范對這個區域規定了兩種異常情況:StackOverflowError和OutOfMemoryError異常。
4.Java堆: Java堆是被所有的線程共享的一塊內存區域,在虛擬機啟動時創建。Java堆的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內存。 Java堆是垃圾回收器管理的主要區域,從內存回收的角度看,由於現在收集器基本都采用分代收集算法,所以Java堆可以細分為:新生代、老生代;從內存分配的角度看,線程共享的Java堆可能划分出多個線程私有的分配緩沖區(TLAB)。 Java堆可以處於物理上不連續的內存空間中,只要邏輯上是連續的即可。 Java虛擬機規范規定,如果在堆上沒有內存完成實例分配,並且堆上也無法再擴展時,將會拋出OutOfMemoryError異常。 Java堆內存的OOM異常: 內存泄露:指程序中一些對象不會被GC所回收,它始終占用內存,即被分配的對象引用鏈可達但已無用。 內存溢出:程序運行過程中無法申請到足夠的內存而導致的一種錯誤。內存溢出通常發生於OLD段或Perm段垃圾回收后,仍然無內存空間容納新的Java對象的情況。
5.方法區: 被所有的線程共享的一塊內存區域。它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。 不需要連續的內存和可以選擇固定大小或者可擴展之外,還可以選擇不實現垃圾回收。 Java虛擬機規范規定,當方法區無法滿足內存分配的需求時,將拋出OutOfMemoryError異常 - 請介紹一下List和ArrayList的區別
List:是一個有序的集合,可以包含重復的元素。提供了按索引訪問的方式。它繼承Collection。List有兩個重要的實現類:ArrayList和LinkedList。
ArrayList:我們可以將其看作是能夠自動增長容量的數組。
1.ArrayList底層采用數組實現,當使用不帶參數的構造方法生成ArrayList對象時,實際上會在底層生成一個長度為10的Object類型數組。
2.如果增加的元素個數超過了10個,那么ArrayList底層會新生成一個數組,長度為原數組的1.5倍+1,然后將原數組的內容復制到新數組當中,並且后續增加的內容都會放到新數組當中。當新數組無法容納增加的元素時,重復該過程。
3.對於ArrayList元素的刪除操作,需要將被刪除元素的后續元素向前移動,代價比較高。
4.集合當中只能放置對象的引用,無法放置原生數據類型,我們需要使用原生數據類型的包裝類才能加入到集合當中。
5.集合當中放置的都是Object類型,因此取出來的也是Object類型,那么必須要使用強制類型轉換將其轉換為真正的類型(放置進去的類型) -
請問有哪幾種垃圾回收算法
垃圾回收(Garbage Collection)是Java虛擬機(JVM)垃圾回收器提供的一種用於在空閑時間不定時回收無任何對象引用的對象占據的內存空間的一種機制。 引用:如果Reference類型的數據中存儲的數值代表的是另外一塊內存的起始地址,就稱這塊內存代表着一個引用。
(1)強引用(Strong Reference):如“Object obj = new Object()”,這類引用是Java程序中最普遍的。只要強引用還存在,垃圾收集器就永遠不會回收掉被引用的對象。
(2)軟引用(Soft Reference):它用來描述一些可能還有用,但並非必須的對象。在系統內存不夠用時,這類引用關聯的對象將被垃圾收集器回收。JDK1.2之后提供了SoftReference類來實現軟引用。
(3)弱引用(Weak Reference):它也是用來描述非須對象的,但它的強度比軟引用更弱些,被弱引用關聯的對象只能生存到下一次垃圾收集發生之前。當垃圾收集器工作時,無論當前內存是否足夠,都會回收掉只被弱引用關聯的對象。在JDK1.2之后,提供了WeakReference類來實現弱引用。
(4)虛引用(Phantom Reference):最弱的一種引用關系,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象實例。為一個對象設置虛引用關聯的唯一目的是希望能在這個對象被收集器回收時收到一個系統通知。JDK1.2之后提供了PhantomReference類來實現虛引用。
垃圾:無任何對象引用的對象。
判斷對象是否是垃圾的算法: 引用計數算法(Reference Counting Collector)、根搜索算法(Tracing Collector)
回收:清理“垃圾”占用的內存空間而非對象本身。
Tracing算法(Tracing Collector) 標記—清除算法:分為“標記”和“清除”兩個階段:首先標記出所需回收的對象,在標記完成后統一回收掉所有被標記的對象,它的標記過程其實就是前面的根搜索算法中判定垃圾對象的標記過程。
Compacting算法(Compacting Collector)標記—整理算法:標記的過程與標記—清除算法中的標記過程一樣,但對標記后出的垃圾對象的處理情況有所不同,它不是直接對可回收對象進行清理,而是讓所有的對象都向一端移動,然后直接清理掉端邊界以外的內存。在基於Compacting算法的收集器的實現中,一般增加句柄和句柄表。
Copying算法(Copying Collector):將內存按容量分為大小相等的兩塊,每次只使用其中的一塊(對象面),當這一塊的內存用完了,就將還存活着的對象復制到另外一塊內存上面(空閑面),然后再把已使用過的內存空間一次清理掉。
Adaptive算法(Adaptive Collector):監控當前堆的使用情況,並將選擇適當算法的垃圾收集器。 發生地點:一般發生在堆內存中,因為大部分的對象都儲存在堆內存中。
(堆內存為了配合垃圾回收有什么不同區域划分,各區域有什么不同?)
Java的堆內存基於Generation算法(Generational Collector)划分為新生代、年老代和持久代。新生代又被進一步划分為Eden和Survivor區,最后Survivor由FromSpace(Survivor0)和ToSpace(Survivor1)組成。所有通過new創建的對象的內存都在堆中分配,其大小可以通過-Xmx和-Xms來控制。分代收集基於這樣一個事實:不同的對象的生命周期是不一樣的。因此,可以將不同生命周期的對象分代,不同的代采取不同的回收算法進行垃圾回收(GC),以便提高回收效率。
按執行機制划分Java有四種類型的垃圾回收器:
(1)串行垃圾回收器(Serial Garbage Collector)
(2)並行垃圾回收器(Parallel Garbage Collector)
(3)並發標記掃描垃圾回收器(CMS Garbage Collector)
(4)G1垃圾回收器(G1 Garbage Collector) 發生時間:程序空閑時間不定時回收。 - 請你說一下Java的內存結構是什么,全局變量、臨時變量、靜態變量分別存在哪里,堆分為哪幾塊,比如說新生代老生代,那么新生代又分為什么
代碼區:是編譯器生成的一個exe區段,存放函數體的二進制代碼
棧區:存放函數的參數,局部變量的值等,其操作方式類似於數據結構中的棧,const局部變量也是放在棧里
堆區:就是malloc和new之類的內存所在區段,一般由程序員分配釋放,分配方式類似於鏈表
靜態數據區:是編譯器生成的一個exe區段,初始和未初始化的全局變量和局部變量都放在這里,
常量區:是編譯器生成的一個exe區段,const全局變量也放在常量區。
全局變量,臨時變量,靜態變量分別存在哪里?
局部變量保存在棧中,全局變量和靜態變量存儲在靜態數據區。
堆分為哪幾塊,比如說新生代老生代,那么新生代又分為什么?
java垃圾收集管理器的主要區域,因此很多時候被稱為“GC堆”。 分為新生代和老年代; 新生代分為:Eden和Survivor。 - 請說明Java的接口和C++的虛類的相同和不同處。
參考答案:
由於Java不支持多繼承,而有可能某個類或對象要使用分別在幾個類或對象里面的方法或屬性,現有的單繼承機制就不能滿足要求。
與繼承相比,接口有更高的靈活性,因為接口中沒有任何實現代碼。當一個類實現了接口以后,該類要實現接口里面所有的方法和屬性,並且接口里面的屬性在默認狀態下面都是public static,所有方法默認情況下是public.一個類可以實現多個接口。
網友答案:相同之處:
都不能實例化。不相同之處:
1.一個子類只能繼承一個抽象類(虛類),但能實現多個接口
2.一個抽象類可以有構造方法,接口沒有構造方法
3.一個抽象類中的方法不一定是抽象方法,即其中的方法可以有實現(有方法體),接口中的方法都是抽象方法,不能有方法體,只有方法聲明
4.一個抽象類可以是public、protected,接口只有public
5.一個抽象類中的方法可以是public、private、protected、default,接口中的方法只能是public和default修飾,實際上都是public的abstract方法
補充:
接口是一類特殊的抽象類,是更抽象的抽象類,你可以這樣理解。抽象類是一個不完整的類,接口只定義了一些功能。
- 簡單談談你對內存泄漏的理解
當一個對象已經不需要再使用本該被回收時,另外一個正在使用的對象持有它的引用從而導致它不能被回收,這導致本該被回收的對象不能被回收而停留在堆內存中,這就產生了內存泄漏。
內存泄漏是造成應用程序OOM的主要原因之一。
我們知道Android系統為每個應用程序分配的內存是有限的,而當一個應用中產生的內存泄漏比較多時,這就難免會導致應用所需要的內存超過系統分配的內存限額,這就造成了內存溢出從而導致應用Crash。
常見的內存泄漏:
1、單例造成的內存泄漏 由於單例的靜態特性使得其生命周期和應用的生命周期一樣長,如果一個對象已經不再需要使用了,而單例對象還持有該對象的引用,就會使得該對象不能被正常回收,從而導致了內存泄漏。
2、非靜態內部類創建靜態實例造成的內存泄漏 非靜態內部類默認會持有外部類的引用,而該非靜態內部類又創建了一個靜態的實例,該實例的生命周期和應用的一樣長,這就導致了該靜態實例一直會持有該Activity的引用,從而導致Activity的內存資源不能被正常回收。
3、Handler造成的內存泄漏
4、線程造成的內存泄漏 如果任務在Activity銷毀之前還未完成,那么將導致Activity的內存資源無法被回收,從而造成內存泄漏。
5、資源未關閉造成的內存泄漏 對於使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源,應該在Activity銷毀時及時關閉或者注銷,否則這些資源將不會被回收,從而造成內存泄漏。
6、使用ListView時造成的內存泄漏
7、集合容器中的內存泄露
8、WebView造成的泄露
避免內存泄漏:
1、在涉及使用Context時,對於生命周期比Activity長的對象應該使用Application的Context。
2、對於需要在靜態內部類中使用非靜態外部成員變量(如:Context、View ),可以在靜態內部類中使用弱引用來引用外部類的變量來避免內存泄漏。
3、對於不再需要使用的對象,顯示的將其賦值為null,比如使用完Bitmap后先調用recycle(),再賦為null。
4、保持對對象生命周期的敏感,特別注意單例、靜態對象、全局性集合等的生命周期。
5、對於生命周期比Activity長的內部類對象,並且內部類中使用了外部類的成員變量,可以這樣做避免內存泄漏: 1)將內部類改為靜態內部類 2)靜態內部類中使用弱引用來引用外部類的成員變量 - Hibernate中SessionFactory和Session是線程安全的嗎?這兩個線程是否能夠共享同一個Session?
SessionFactory對應Hibernate的一個數據存儲的概念,它是線程安全的,可以被多個線程並發訪問。SessionFactory一般只會在啟動的時候構建。對於應用程序,最好將SessionFactory通過單例模式進行封裝以便於訪問。
Session是一個輕量級非線程安全的對象(線程間不能共享session),它表示與數據庫進行交互的一個工作單元。Session是由SessionFactory創建的,在任務完成之后它會被關閉。Session是持久層服務對外提供的主要接口。Session會延遲獲取數據庫連接(也就是在需要的時候才會獲取)。為了避免創建太多的session,可以使用ThreadLocal將session和當前線程綁定在一起,這樣可以讓同一個線程獲得的總是同一個session。Hibernate 3中SessionFactory的getCurrentSession()方法就可以做到。 - 匯編語言中有一種移位指令叫做循環左移(ROL),現在有個簡單的任務,就是用字符串模擬這個指令的運算結果。對於一個給定的字符序列S,請你把其循環左移K位后的序列輸出。例如,字符序列S=”abcXYZdef”,要求輸出循環左移3位后的結果,即“XYZdefabc”
public class Solution { public String LeftRotateString(String str,int n) { int len = str.length(); if (len == 0) return str; n %= len; str += str; return str.substring(n,n+len); } }
2.16
- AOP的原理是什么?
AOP是指面向切面編程,Spring中的AOP主要是通過JDK的動態代理以及cglib來實現AOP功能。JDK動態代理,只能對實現了接口的類生成代理,而不是針對類,該目標類型實現的接口都將被代理。原理是通過在運行期間創建一個接口的實現類來完成對目標對象的代理。;cglib主要針對類實現代理,對是否實現接口無要求。原理是對指定的類生成一個子類,覆蓋其中的方法。
https://blog.csdn.net/wyl6019/article/details/80136000 - 請問aop的應用場景有哪些?
AOP是指面向切面編程,在某一個方法之前或者之后做一些額外的操作,比如說日志記錄,權限判斷,異常統計和事務處理等,可以利用AOP將功能代碼從業務邏輯代碼中分離出來。 - 請問error和exception有什么區別?
error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。
exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。
Exception 和 Error 都是繼承了 Throwable 類,在 Java 中只有 Throwable 類型的實例才可以被拋出(throw)或者捕獲(catch),它是異常處理機制的基本組成類型。
Error 是指在正常情況下,不大可能出現的情況,絕大部分的 Error 都會導致程序(比如 JVM 自身)處於非正常的、不可恢復狀態。既然是非正常情況,所以不便於也不需要捕獲,常見的比如 OutOfMemoryError 之類,都是 Error 的子類。
Exception 又分為可檢查(checked)異常和不檢查(unchecked)異常,可檢查異常在源代碼里必須顯式地進行捕獲處理,這是編譯期檢查的一部分。不檢查異常就是所謂的運行時異常,類似 NullPointerException、ArrayIndexOutOfBoundsException 之類,通常是可以編碼避免的邏輯錯誤,具體根據需要來判斷是否需要捕獲,並不會在編譯期強制要求。