JVM規(guī)范
如果try語句中有return,返回的是try語句塊中的變量值勿璃,詳細執(zhí)行過程如下;
如果有返回值推汽,就把返回值保存在局部變量中补疑,打上斷點,繼續(xù)執(zhí)行其它語句塊
執(zhí)行jsr指令歹撒,跳到finally語句塊當中
執(zhí)行完finally語句中的程序后莲组,回到之前斷點處,返回保存在局部變量表里的值
總的來說finally必定執(zhí)行栈妆,不過finally中的變量操作不會影響try中被保存為局部變量的返回值胁编,除非finally中也有return指令厢钧,這樣一來忽略try中的return語句
JVM內(nèi)存
一個java源程序首先會被編譯成字節(jié)碼文件,每個java程序都運行在自己的jvm上嬉橙,然后告知jvm程序的運行入口早直,再被jvm通過字節(jié)碼解釋器加載運行。jvm每遇到一個線程會分配一個計數(shù)器市框、虛擬機棧霞扬、本地方法棧,這三者都是線程私有的枫振,其周期與線程相同喻圃,線程結束時回收內(nèi)存。
函數(shù)每次被調(diào)用時,在內(nèi)存中都有自己的活動記錄(activation record),稱為椃嗦耍空間(stack). Java 的方法在調(diào)用時在 JVM 棧中為其分配一個棧幀(Java椄模空間的一個片段),可以稱之為方法棧. 原則上,所有對象都在堆空間(Heap)中分配。
方法區(qū)
線程共享杖小,存放所加載的類的信息肆汹、類中的靜態(tài)變量、final常量予权、field信息昂勉、方法信息,該區(qū)域全局共享扫腺。
堆
線程共享
程序計數(shù)器
線程私有
虛擬機棧
線程私有
本地方法棧
線程私有
參考文獻
jvm中一個字節(jié)以下的整形數(shù)據(jù)會在jvm啟動時候加載進內(nèi)存岗照。
java是自動管理內(nèi)存的,通常情況下程序運行到穩(wěn)定狀態(tài)笆环,內(nèi)存大小也達到一個穩(wěn)定的值攒至,但是內(nèi)存泄漏導致Gc不能回收泄露的垃圾,內(nèi)存不斷變大咧织,最終超出內(nèi)存界限嗓袱,拋出OutOfMemoryExpection
類的加載順序
- 父類靜態(tài)代碼塊(包括靜態(tài)初始化塊,靜態(tài)屬性习绢,但不包括靜態(tài)方法)
- 子類靜態(tài)代碼塊(包括靜態(tài)初始化塊,靜態(tài)屬性蝙昙,但不包括靜態(tài)方法 )
- 父類非靜態(tài)代碼塊( 包括非靜態(tài)初始化塊闪萄,非靜態(tài)屬性 )
- 父類構造函數(shù)
- 子類非靜態(tài)代碼塊 ( 包括非靜態(tài)初始化塊,非靜態(tài)屬性 )
- 子類構造函數(shù)
初始化
立即初始化的情況
- 使用new關鍵字實例化對象的時候奇颠、讀取或設置一個類的靜態(tài)字段的時候败去,已經(jīng)調(diào)用一個類的靜態(tài)方法的時候。
- 使用java.lang.reflect包的方法對類進行反射調(diào)用的時候烈拒,如果類沒有初始化圆裕,則需要先觸發(fā)其初始化广鳍。
- 當初始化一個類的時候,如果發(fā)現(xiàn)其父類沒有被初始化就會先初始化它的父類吓妆。
- 當虛擬機啟動的時候赊时,用戶需要指定一個要執(zhí)行的主類(就是包含main()方法的那個類),虛擬機會先初始化這個類行拢;
- 使用動態(tài)語言支持的時候
不會初始化的情況 - 子類引用父類的靜態(tài)字段不會導致子類初始化
- 通過數(shù)值定義來引用類的初始化時候
- 常量在編譯階段會進行常量優(yōu)化祖秒,將常量存入調(diào)用類的常量池中,本質(zhì)上沒有直接引用到定義常量的類舟奠,因此不會觸發(fā)定義常量的類的初始化竭缝。
jdbc
JDBC提供了Statement、PreparedStatement 和 CallableStatement三種方式來執(zhí)行查詢語句沼瘫,其中 Statement 用于通用查詢抬纸, PreparedStatement 用于執(zhí)行參數(shù)化查詢,而 CallableStatement則是用于存儲過程耿戚。
對于PreparedStatement來說松却,數(shù)據(jù)庫可以使用已經(jīng)編譯過及定義好的執(zhí)行計劃,由于 PreparedStatement 對象已預
編譯過溅话,所以其執(zhí)行速度要快于 Statement 對象”
PreparedStatement可以阻止常見的SQL注入式攻擊
Statement
普通的不帶參數(shù)的SQL晓锻,批量更新滚朵、刪除群发,每次執(zhí)行時數(shù)據(jù)庫都需要對sql進行編譯次氨。
PreparedStatement
可變參數(shù)的SQL羹蚣,編譯一次澜沟,執(zhí)行多次夹纫。預編譯的安全性好拄显,有效防止Sql注入問題
CallableStatement
繼承自PreparedStatement将饺,支持調(diào)用存儲過程卵史,提供對輸出战转、輸出參數(shù)的支持
spring事務傳播特性:
事務傳播行為就是多個事務方法相互調(diào)用時,事務如何在這些方法間傳播以躯。spring支持7種事務傳播行為:
propagation_requierd(需要):如果當前沒有事務槐秧,就新建一個事務,如果已存在一個事務中忧设,加入到這個事務中刁标,這是最常見的選擇。
propagation_supports(支持):支持當前事務址晕,如果沒有當前事務膀懈,就以非事務方法執(zhí)行。
propagation_mandatory(強制):使用當前事務谨垃,如果沒有當前事務启搂,就拋出異常硼控。
propagation_required_new(需要新建):新建事務,如果當前存在事務胳赌,把當前事務掛起牢撼。
propagation_not_supported(不支持):以非事務方式執(zhí)行操作,如果當前存在事務匈织,就把當前事務掛起浪默。
propagation_never(絕不):以非事務方式執(zhí)行操作,如果當前事務存在則拋出異常缀匕。
propagation_nested(嵌套):如果當前存在事務纳决,則在嵌套事務內(nèi)執(zhí)行。如果當前沒有事務乡小,則執(zhí)行與propagation_required類似的操作
原文鏈接
Servlet與CGI
CGI
cgi(公共網(wǎng)關接口)是HTTP服務器與你或其它機器上的程序進行交互的工具阔加,運行在網(wǎng)絡服務器上,cgi程序常用來處理來自表單的輸入信息满钟,并在服務器產(chǎn)生相應的處理胜榔,cgi使得網(wǎng)頁具有交互功能。
cgi處理過程
通過網(wǎng)絡把用戶請求發(fā)送到服務器
服務器接收請求并將請求交給cgi處理
cgi把處理結果返回給服務器
服務器把結果返回給用戶
Servlet
服務器端的java運用程序湃番,可以生成動態(tài)web頁面夭织,擔當客戶請求與服務器相應的中間層。
工作過程
客戶端發(fā)送請求給服務器吠撮,服務器啟動并調(diào)用servlet尊惰,servlet根據(jù)客戶端請求生成響應內(nèi)容并傳給服務器。
兩者比較
servlet效率更高泥兰、容易使用弄屡;傳統(tǒng)CGI每個請求都要啟動一個重量級的操作系統(tǒng)線程,Servlet中每個請求由一個輕量級的線程處理鞋诗,通過多線程方式運行service方法膀捷,一個實例服務于多個請求。傳統(tǒng)cgi對同一個cgi程序的并發(fā)請求處理方式是在內(nèi)存當中重復裝載n次cgi程序代碼削彬;而對于servlet全庸,處理請求的是n個線程,所以只需要一份servlet類代碼吃警。
Servlet 生命周期
Servlet 生命周期可被定義為從創(chuàng)建直到毀滅的整個過程糕篇。以下是 Servlet 遵循的過程:
容器通過類加載器使用servlet類對應的文件加載servlet
調(diào)用servlet構造函數(shù)創(chuàng)建servlet對象
Servlet 初始化后調(diào)用 init () 方法。
Servlet 調(diào)用 service() 方法來處理客戶端的請求酌心。
Servlet 銷毀前調(diào)用 destroy() 方法。
最后挑豌,Servlet 是由 JVM 的垃圾回收器進行垃圾回收的安券。
Struts工作原理
MVC為Model-View-Controller的縮寫墩崩,是一種常用的設計模式。MVC減弱了業(yè)務邏輯接口和數(shù)據(jù)接口之間的耦合侯勉,以及讓視圖層更富于變化鹦筹。
Struts是MVC的一種實現(xiàn),它將Servlet和JSP標記用作實現(xiàn)的一部分址貌。
Controller
有一個XML文件Struts-config.xml铐拐,與之相關聯(lián)的是Controller,在Struts中练对,承擔MVC中Controller角色的是ActionServlet遍蟋。ActionServlet是一個通用的控制組件。提供了處理所有發(fā)送到 Struts的HTTP請求的入口點螟凭。它截取和分發(fā)這些請求到相應的Action的子類虚青。另外控制組件也負責用相應的請求參數(shù)填充Action、From(通常稱之為FromBean),并傳給Action類(通常稱之為ActionBean)螺男。動作類實現(xiàn)核心商業(yè)邏輯棒厘,它可以訪問JavaBean或調(diào)用EJB。最后Action類把控制權傳給后續(xù)的JSP文件下隧,后者生成視圖奢人。所有這些控制邏輯利用Struts-config.xml文件來配置。
視圖:主要由JSP生成頁面完成視圖淆院,Struts提供豐富的JSP 標簽庫: Html何乎,Bean,Logic迫筑,Template等宪赶,這有利于分開表現(xiàn)邏輯和程序邏輯。
模 型:模型以一個或多個java bean的形式存在脯燃。這些bean分為三類:Action Form搂妻、Action、JavaBean or EJB辕棚。Action Form通常稱之為FormBean欲主,封裝了來自于Client的用戶請求信息,如表單信息逝嚎。Action通常稱之為ActionBean扁瓢,獲取從 ActionSevlet傳來的FormBean,取出FormBean中的相關信息补君,并做出相關的處理引几,一般是調(diào)用Java Bean或EJB等。
流程:在Struts中挽铁,用戶的請求一般以.do作為請求服務名伟桅,所有的.do請求均被指向 ActionSevlet敞掘,ActionSevlet根據(jù)Struts-config.xml中的配置信息,將用戶請求封裝成一個指定名稱的 FormBean楣铁,并將此FormBean傳至指定名稱的ActionBean玖雁,由ActionBean完成相應的業(yè)務操作,如文件操作盖腕,數(shù)據(jù)庫操作等赫冬。 每一個*.do均有對應的FormBean名稱和ActionBean名稱,這些在Struts-config.xml中配置溃列。
核心:Struts的核心是ActionSevlet劲厌,ActionSevlet的核心是Struts-config.xml。
Struts 1與 Struts 2
Action類
Struts1要求Action類繼承一個抽象類哭廉,Struts1使用抽象類編程而不是接口
Struts2可以實現(xiàn)Action接口也可以不實現(xiàn)脊僚,Struts2提供一個ActionSuport基類去實現(xiàn)常用接口。Action接口不是必須的遵绰,任何有execute的標識的
POJO都有可能成為struts2的Action的對象
線程模式
Struts1的Action是單例模式并且是線程安全的辽幌,僅有Action一個實例來處理所有請求。單策略模式限制了Struts1 Action能做的事椿访。比且在開發(fā)時要
注意Action資源必須是線程安全比且是同步的乌企。
Struts2的Action對象為每個請求產(chǎn)生一個實例,因此沒有線程安全問題成玫。
Servlet依賴
Struts1 Action依賴與Servlet API加酵,因為當一個Action被調(diào)用時HttpServletRequest和HttpServletResponse被傳遞給execute方法。
Struts2 Action不依賴與容器哭当,允許Action脫離容器被單獨測試猪腕。如果需要,struts2依然可以訪問初始的request和response钦勘。但是陋葡,其他的元素減
少或者消除了直接訪問HttpServletRequest和HttpServletResponse的必要性。
可測性
測試Struts1 Action的一個主要問題是execute方法暴漏了Servlet API(這使得測試要依賴于容器)彻采。一個第三方擴展--Struts TestCase--提供了一套Struts1的模擬對象(來進行測試)
struts2 Action可以通過初始化腐缤、設置屬性、調(diào)用方法來測試肛响,“依賴注入”支持也使測試更容易岭粤。
捕獲輸入
struts1使用ActionForm對象捕獲輸入。所有ActionForm必須繼承一個基類特笋。因為其他JavaBean不能用作ActionForm剃浇,開發(fā)者經(jīng)常創(chuàng)建多余的基類不或輸入。動態(tài)Bean(DynaBeans)可以作為創(chuàng)建傳統(tǒng)ActionForm的選擇,但是偿渡,開發(fā)者可能是在重新描述(創(chuàng)建)已經(jīng)存在的JavaBean(仍然會導致有沉余的JavaBean)臼寄。
Struts2直接使用Acrtion屬性作為輸入屬性霸奕,消除了對第二個輸入對象的請求溜宽。輸入屬性可能是有自己(子)屬性的Rich對象類型。Action屬性能過通過web頁面上的Taglibs訪問质帅。struts2也支持ActionForm模式适揉。Richard對象類型,包括業(yè)務對象煤惩,能夠用作輸入/輸出對象嫉嘀。這種ModelDriven特性簡化了Taglib對POJO輸入對象的引用。
表達式語言
Struts1整合了JSTL魄揉,因此使用JSTL EL剪侮。這種EL有基本對象圖遍歷,但是對集合和索引屬性的支持很脆弱洛退。
Struts2可以使用JSTL瓣俯,但是也支持一個更強大和靈活的表達式語言--“object graph Notation Language”(OGNL)
綁定值到頁面(view)
Struts1使用標準JSP機制吧對象綁定到頁面中來訪問。
struts2使用ValueStack技術兵怯,使taglib能夠訪問值而不需要把你的頁面(view)和對象綁定起來彩匕。ValueStack策略允許通過一系列名稱相同但類型不同的屬性重同頁面(view)
類型轉換
Struts1 ActionForm屬性通常都是String類型。struts1使用Commons-Beanutils進行類型轉換媒区。每個類一個轉換器驼仪,對每一個實例來說是不可配置的
struts2 使用OGNL進行類型轉換,提供基本和常用對象的轉換器袜漩。
效驗
Struts1支持在ActionForm的validate方法中手動效驗绪爸,或者通過Commons Validator的擴展來效驗。同一個類可以有不同的效驗內(nèi)容宙攻,但不能效驗子對象奠货。
Struts2支持通過validate方法和XWork效驗框架進行效驗。XWork效驗框架使用為屬性類類型定義的效驗和內(nèi)容效驗粘优,來支持Chain效驗子屬性仇味。
Action執(zhí)行的控制
Struts1支持每一個模塊有單獨的Request Processors(生命周期),但是模塊中的所有Action必須共享相同的生命周期雹顺。
struts2支持通過攔截器堆棧(Interceptor Stacks)為每一個Action創(chuàng)建不能的生命周期丹墨。堆棧能夠根據(jù)需要和不同的Action一起使用。
forword 與redirect
forward
請求轉發(fā)嬉愧,屬于服務器行為贩挣,本質(zhì)上是同一個請求,地址欄不變。
redirect
請求重定向王财,屬于客戶端行為卵迂,本質(zhì)上是兩次請求,地址欄改變绒净。
加載驅動程序的方法
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");
jdbc使用詳細案例
java多線程
java的多線程是搶占機制(不是分時機制)见咒,即是說多個線程處于可運行狀態(tài),但也只有一個線程在運行挂疆。
sleep()與wait()的區(qū)別
sleep()
線程類Thread的方法改览,不釋放對象鎖,作用是暫停線程缤言,但監(jiān)控狀態(tài)仍然保持宝当,結束后自動恢復
wait()
Object類的方法,對象調(diào)用時線程放棄對象鎖胆萧,進入等待此對象的等待鎖定持庆揩,只有針對此對象發(fā)出notify或notifyAll方法后本線程才進入對象鎖定池準備獲取對象鎖進入運行狀態(tài)(此時處于就緒狀態(tài))
異常
運行時異常
都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)跌穗、IndexOutOfBoundsException(下標越界異常)等订晌,這些異常是不檢查異常,程序中可以選擇捕獲處理瞻离,也可以不處理腾仅。這些異常一般是由程序邏輯錯誤引起的,程序應該從邏輯角度盡可能避免這類異常的發(fā)生套利。
運行時異常的特點是Java編譯器不會檢查它推励,也就是說,當程序中可能出現(xiàn)這類異常肉迫,即使沒有用try-catch語句捕獲它验辞,也沒有用throws子句聲明拋出它,也會編譯通過喊衫。
非運行時異常 (編譯異常)
是RuntimeException以外的異常跌造,類型上都屬于Exception類及其子類。從程序語法角度講是必須進行處理的異常族购,如果不處理壳贪,程序就不能編譯通過。如IOException寝杖、SQLException等以及用戶自定義的Exception異常违施,一般情況下不自定義檢查異常。
JSP
靜瑟幕、動態(tài)include
靜態(tài)的include:是jsp的指令來實現(xiàn)的磕蒲,<% @ include file="xx.html"%> 特點是 共享request請求域留潦,先包含再編譯,不檢查包含頁面的變化辣往,靜態(tài)include的結果是把其它jsp引入到當前jsp兔院。
動態(tài)的include:是jsp動作來實現(xiàn)的,<jsp:include page="xx.jsp" flush="true"/> 這個是不共享request請求域站削,先編譯在包含坊萝,是要檢查包含頁面的變化的,動態(tài)include的結構是兩者獨立钻哩,輸出時才合并屹堰。
AWT與Swing
AWT:基于本地方法的C/C++程序,運行速度快街氢,通過調(diào)用操作系統(tǒng)的native方法實現(xiàn),AWT所提供的圖形功能是各種通用型操作系統(tǒng)所提供的圖形功能的交集睦袖,以此實現(xiàn)“一次編譯珊肃,到處運行”的概念。
Swing:純java所寫馅笙,基于AWT的Java程序伦乔,運行速度較慢,對AWT的功能進行了大幅度擴充董习,且Swing在所有平臺表現(xiàn)一致烈和。
在實際運用中使用AWT還是Swing取決于應用程序所部署的平臺類型,例如
- 對于一個嵌入式應用皿淋,目標平臺的硬件資源往往非常有限招刹,而應用程序的運行速度又是項目中至關重要的因素。在這種矛盾的情況下窝趣,簡單而高效的AWT當然成了嵌入式Java的第一選擇疯暑。
- 在普通的基于PC或者是工作站的標準Java應用中,硬件資源對應用程序所造成的限制往往不是項目中的關鍵因素哑舒。所以在標準版的Java中則提倡使用Swing妇拯, 也就是通過犧牲速度來實現(xiàn)應用程序的功能。
Spring特性
參考文章
Spring的核心特性控制反轉和面向切面編程洗鸵。
IOC控制反轉(別名:DI依賴注入)
概念
獲得依賴對象的過程反轉了越锈,由主動轉為了被動,由自身管理轉為IOC容器運行期間動態(tài)的將依賴關系注入到對象中膘滨。
面向對象的編程使得大型項目當中甘凭,對象的耦合程度非常高,牽一發(fā)而動全身吏祸。
而控制反轉的理念既是把復雜系統(tǒng)分解成相互合作的對象对蒲,這些對象類通過封裝以后钩蚊,內(nèi)部實現(xiàn)對外部透明,降低了解決問題的復雜度蹈矮,可以靈活的重用砰逻、擴展。
IOC理論的觀點大致為:借助于”第三方“實現(xiàn)具有依賴關系的對象之間的解耦泛鸟。
IOC容器便是引入的第三方蝠咆。控制反轉指的是將依賴具體實現(xiàn)的控制權由主動轉為被動北滥。引入IOC容器之前刚操,每當對象A需要具體體現(xiàn)與B的依賴關系的時候都需要自行創(chuàng)建、使用對象B再芋,控制權在A自己手上菊霜。引入IOC容器之后,容器會在每當對象A需要依賴B的時候自動將容器中創(chuàng)建好的對象B注入到對象A中济赎。
IOC原理的實現(xiàn)
利用反射特性進行編程鉴逞,根據(jù)給出類名動態(tài)的生成對象。其它細節(jié)還有:IOC把以前在工廠方法中寫死的對象生成代碼司训,改變?yōu)橛膳渲梦募矶x构捡,把工廠和對象生成獨立開來,提高了靈活性和可維護性壳猜。
AOP面向切面編程
面向對象編程OOP的補充和完善勾徽,OOP通過封裝、繼承统扳、多態(tài)很好的建立了縱向的對象層次結構喘帚;AOP將那些與業(yè)務無關卻被業(yè)務模塊共同調(diào)用散布在各處的邏輯封裝起來(命名為Aspect),減少系統(tǒng)的重復代碼闪幽,是OOP橫向上的補充啥辨。
AOP原理實現(xiàn)
具體操作便是將共同的邏輯、方法通過Spring注入到接口調(diào)用的某個地方盯腌。
Spring中AOP代理由IOC容器負責管理溉知、生成,其依賴也由IOC容器負責管理腕够,關于AOP级乍,程序員只需要定義普通業(yè)務組件、定義切入點帚湘、定義增強處理(AOP框架為普通業(yè)務組織注入的處理動作)
Java內(nèi)存模型
java 內(nèi)存模型規(guī)定了所有的變量都存儲在主內(nèi)存中玫荣,但是每個線程會有自己的工作內(nèi)存,線程的工作內(nèi)存保存了該線程中使用了的變量(從主內(nèi)存中拷貝的)大诸,線程對變量的操作都必須在工作內(nèi)存中進行捅厂,不同線程之間無法直接訪問對方工作內(nèi)存中的變量贯卦,線程間變量值從傳遞都要經(jīng)過主內(nèi)存完成
什么是原子性
一個操作是不可中斷的,要么全部執(zhí)行成功要么全部執(zhí)行失敗焙贷,比如銀行轉賬
什么是可見性
當多個線程訪問同一變量時撵割,一個線程修改了這個變量的值,其他線程就能夠立即看到修改的值
什么是有序性
程序執(zhí)行的順序按照代碼的先后順序執(zhí)行
int a = 0;
int b = 2;
像這2句代碼第一句會比第二局先執(zhí)行辙芍,但是jvm在真正執(zhí)行時不一定是第一句在第二句之前啡彬,這里涉及一個概念叫做指令重排,處理器為了提高程序運行效率故硅,可能會對輸入代碼進行優(yōu)化庶灿,它不保證程序中各個語句的執(zhí)行先后順序同代碼中的順序一致,但是它會保證程序最終執(zhí)行結果和代碼順序執(zhí)行的結果是一致的吃衅。比如上面的代碼誰先執(zhí)行對最終的程序結果并沒有影響往踢,那么就有可能在執(zhí)行過程中,語句2先執(zhí)行而語句1后執(zhí)行捐晶。
在指令重排時會考慮指令之間的數(shù)據(jù)依賴性菲语,比如2依賴了1的數(shù)值,那么處理器會保證1在2之前執(zhí)行惑灵。
但是在多線程的情況下,指令重排就會有影響了眼耀。
volatile到底做了什么
- 禁止了指令重排
- 保證了不同線程對這個變量進行操作時的可見性英支,即一個線程修改了某個變量值,這個新值對其他線程是立即可見的
- 不保證原子性(線程不安全)
其它
在一個含有基本數(shù)據(jù)類型的比較語句中哮伟,比較的時候比較的是數(shù)值干花。