不論是物理機還是虛擬機,大部分的程序代碼從開始編譯到最終轉化成物理機的目標代碼或虛擬機能執行的指令集之前,都會按照如下圖所示的各個步驟進行:
Ⅱ AOP是什麼意思
AOP為Aspect
Oriented
Programming的縮寫,是面向切面編程,通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生范型。
AOP的出現彌補了OOP的這點不足,AOP
是一個概念,一個規范,本身並沒有設定具體語言的實現,AOP是基於動態代理模式。AOP是方法級別的,要測試的方法不能為static修飾,因為介面中不能存在靜態方法,編譯就會報錯。
AOP可以分離業務代碼和關注點代碼(重復代碼),在執行業務代碼時,動態的注入關注點代碼。切面就是關注點代碼形成的類。Spring
AOP中的動態代理主要有兩種方式,JDK動態代理和CGLIB動態代理。JDK動態代理通過反射來接收被代理的類,並且要求被代理的類必須實現一個介面。
(2)位元組碼增強編譯期擴展閱讀
AOP實現的關鍵在於AOP框架自動創建的AOP代理,AOP代理主要分為靜態代理和動態代理,靜態代理的代表為AspectJ。而動態代理則以Spring
AOP為代表,靜態代理是編譯期實現,動態代理是運行期實現,可想而知前者擁有更好的性能。
靜態代理是編譯階段生成AOP代理類,也就是說生成的位元組碼就織入了增強後的AOP對象;動態代理則不會修改位元組碼,而是在內存中臨時生成一個AOP對象,這個AOP對象包含了目標對象的全部方法,並且在特定的切點做了增強處理,並回調原對象的方法。
參考資料來源;搜狗網路--AOP
Ⅲ java位元組碼加強是什麼意思,加強有什麼好處。
位元組碼是Java程序的中間表示,好處如下:
在調試,優化性能和調節內存分配時,這項知識是至關重要的。
了解編譯器寫的代碼生成的匯編指令,有助於認識到如何以不同的編碼實現內存或性能目標。
此外,當跟蹤一個問題的時候,使用調試器(debugger)對源碼反匯編,然後對正在執行的匯編代碼進行單步調試是有益的。
採用位元組碼,就可以克服不同平台之間編譯器的區別,統一使用虛擬的位元組碼就行編譯運行。
Ⅳ POJO與PO的概念及區別
POJO = pure old java object or plain ordinary java object or what ever.
PO = persisent object 持久對象
就是說在一些Object/Relation Mapping工具中,能夠做到維護資料庫表記錄的persisent object完全是一個符合Java Bean規范的純Java對象,沒有增加別的屬性和方法。全都是這樣子的:
public class User {
private long id;
private String name;
public void setId(long id) {
this.id = id;
}
public void setName(String name) {
this.name=name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
}
--------------------------------------------------------------------------------
首先要區別持久對象和POJO。
持久對象實際上必須對應資料庫中的entity,所以和POJO有所區別。比如說POJO是由new創建,由GC回收。但是持久對象是insert資料庫創建,由資料庫delete刪除的。基本上持久對象生命周期和資料庫密切相關。另外持久對象往往只能存在一個資料庫Connection之中,Connnection關閉以後,持久對象就不存在了,而POJO只要不被GC回收,總是存在的。
由於存在諸多差別,因此持久對象PO(Persistent Object)在代碼上肯定和POJO不同,起碼PO相對於POJO會增加一些用來管理資料庫entity狀態的屬性和方法。而ORM追求的目標就是要PO在使用上盡量和POJO一致,對於程序員來說,他們可以把PO當做POJO來用,而感覺不到PO的存在。
JDO的實現方法是這樣的:
1、編寫POJO
2、編譯POJO
3、使用JDO的一個專門工具,叫做Enhancer,一般是一個命令行程序,手工運行,或者在ant腳本裡面運行,對POJO的class文件處理一下,把POJO替換成同名的PO。
4、在運行期運行的實際上是PO,而不是POJO。
該方法有點類似於JSP,JSP也是在編譯期被轉換成Servlet來運行的,在運行期實際上運行的是Servlet,而不是JSP。
Hibernate的實現方法比較先進:
1、編寫POJO
2、編譯POJO
3、直接運行,在運行期,由Hibernate的CGLIB動態把POJO轉換為PO。
由此可以看出Hibernate是在運行期把POJO的位元組碼轉換為PO的,而JDO是在編譯期轉換的。一般認為JDO的方式效率會稍高,畢竟是編譯期轉換嘛。但是Hibernate的作者Gavin King說CGLIB的效率非常之高,運行期的PO的位元組碼生成速度非常之快,效率損失幾乎可以忽略不計。
實際上運行期生成PO的好處非常大,這樣對於程序員來說,是無法接觸到PO的,PO對他們來說完全透明。可以更加自由的以POJO的概念操縱PO。另外由於是運行期生成PO,所以可以支持增量編譯,增量調試。而JDO則無法做到這一點。實際上已經有很多人在抱怨JDO的編譯期Enhancer問題了,而據說JBossDO將採用運行期生成PO位元組碼,而不採用編譯期生成PO位元組碼。
另外一個相關的問題是,不同的JDO產品的Enhancer生成的PO位元組碼可能會有所不同,可能會影響在JDO產品之間的可移植性,這一點有點類似EJB的可移植性難題。
--------------------------------------------------------------------------------
由這個問題另外引出一個JDO的缺陷。
由於JDO的PO狀態管理方式,所以當你在程序裡面get/set的時候,實際上不是從PO的實例中取values,而是從JDO
在JDO中,也可以通過一些辦法使得PO可以在PM外面使用,比如說定義PO是transient的,但是該PO在PM關閉後就沒有PO identity了。無法進行跨PM的狀態管理。
而Hibernate是從PO實例中取values的,所以即使Session關閉,也一樣可以get/set,可以進行跨Session的狀態管理。
在分多層的應用中,由於持久層和業務層和web層都是分開的,此時Hibernate的PO完全可以當做一個POJO來用,也就是當做一個VO,在各層間自由傳遞,而不用去管Session是開還是關。如果你把這個POJO序列化的話,甚至可以用在分布式環境中。(不適合lazy loading的情況)
但是JDO的PO在PM關閉後就不能再用了,所以必須在PM關閉前把PO拷貝一份VO,把VO傳遞給業務層和web層使用。在非分布式環境中,也可以使用ThreadLocal模式確保PM始終是打開狀態,來避免每次必須進行PO到VO的拷貝操作。但是不管怎麼說,這總是權宜之計,不如Hibernate的功能強。
State Manager?中取出來,所以一旦PM關閉,PO就不能進行存取了。
Ⅳ 什麼是Java位元組碼
它是程序的一種低級表示,可以運行於Java虛擬機上。將程序抽象成位元組碼可以保證Java程序在各種設備上的運行
Java號稱是一門「一次編譯到處運行」的語言,從我們寫的java文件到通過編譯器編譯成java位元組碼文件(.class文件),這個過程是java編譯過程;而我們的java虛擬機執行的就是位元組碼文件。不論該位元組碼文件來自何方,由哪種編譯器編譯,甚至是手寫位元組碼文件,只要符合java虛擬機的規范,那麼它就能夠執行該位元組碼文件。
JAVA程序的運行
因為Java具有跨平台特性,為了實現這個特性Java執行在一台虛擬機上,這台虛擬機也就是JVM,Java通過JVM屏蔽了不同平台之間的差異,從而做到一次編譯到處執行。JVM位於Java編譯器和OS平台之間,Java編譯器只需面向JVM,生成JVM能理解的代碼,這個代碼即位元組碼,JVM再將位元組碼翻譯成真實機器所能理解的二進制機器碼。
位元組碼是怎麼產生的?
我們所編寫的程序都是.java格式,通常在執行的時候也許點擊一下eclipse的運行鍵就可以在控制台看到運行結果,但是也可以更酷一些,如果你裝了JDK,那就可以直接在以命令行的方式編譯運行你的.java文件,編譯後會形成.class文件,這個.class文件即位元組碼。
位元組碼怎麼解讀?
上圖是編譯好的位元組碼文件,即一堆16進制的位元組,如果使用IDE去打開,也許看到的是已經被反編譯的我們所熟悉的java代碼,但這才是純正的位元組碼
這里只介紹位元組碼由哪些部分組成, 具體的意思自行網路或者看文尾的連接, 有較為詳細的講解
上圖即位元組碼文件的組成部分, Class文件的結構不像XML等描述語言那樣鬆散自由。由於它沒有任何分隔符號,
所以,以上數據項無論是順序還是數量都是被嚴格限定的。哪個位元組代表什麼含義,長度是多少,先後順序如何,都不允許改變, 如上圖左側即每一部分規定的長度
魔數(Magic Number)
魔數是用來區分文件類型的一種標志,一般都是用文件的前幾個位元組來表示。
比如0XCAFE BABE表示的是class文件,那麼有人會問,文件類型可以通過文件名後綴來判斷啊?是的,但是文件名是可以修改的(包括後綴),那麼為了保證文件的安全性,將文件類型寫在文件內部來保證不被篡改。
至於為什麼是CAFE BABE估計大家也能猜到, 程序員與咖啡的不解之緣
版本號(Version)
版本號含主版本號和次版本號,都是各佔2個位元組。在此Demo種為0X0000 0033。其中前面的0000是次版本號,後面的0033是主版本號。通過進制轉換得到的是次版本號為0,主版本號為51。高版本的JDK能向下兼容以前版本的Class文件,但不能運行以後版本的Class文件,即使文件格式未發生任何變化. 這就是target參數的用處,可以在使用JDK 1.7編譯時指定-target 1.5
常量池(Constant Pool)
常量池是Class文件中的資源倉庫, 量池中主要存儲2大類常量:字面量和符號引用。字面量如文本字元串,java中聲明為final的常量值等等,而符號引用如類和介面的全局限定名,欄位的名稱和描述符,方法的名稱和描述符。常量池是一個表結構,在表的內容前有一個類型的計數器,表示常量池的長度
上面的表中描述了11中數據類型的結構,其實在jdk1.7之後又增加了3種(CONSTANT_MethodHandle_info,CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)。這樣算起來一共是14種
訪問標志(Access_Flag)
訪問標志信息包括該Class文件是類還是介面,是否被定義成public,是否是abstract,如果是類,是否被聲明成final。通過上面的源代碼,我們知道該文件是類並且是public。
0x 00 21:是0×0020和0×0001的並集。其中0×0020這個標志值涉及到位元組碼指令
類索引(This Class Name)
類索引用於確定類的全限定名
0×00 03 表示引用第3個常量,同時第3個常量引用第19個常量,查找得」com/demo/Demo」。#3.#19
父類索引(Super Class Name)
0×00 04 同理:#4.#20(java/lang/Object)
介面索引(Interfaces)
通過上邊位元組碼圖可以看到,這個介面有2+n個位元組,前兩個位元組表示的是介面數量,後面跟著就是介面的表。我們這個類沒有任何介面,所以應該是0000。果不其然,查找位元組碼文件得到的就是0000。
欄位表集合(fields)
欄位表用於描述類和介面中聲明的變數。這里的欄位包含了類級別變數以及實例變數,但是不包括方法內部聲明的局部變數。接下來就是2+n個欄位屬性。我們只有一個屬性a,所以應該是0001。查找文件果不其然是0001。
該區域含有欄位的訪問標志, 訪問許可權, 欄位的名稱索引, 欄位的描述符索引, 屬性表
描述符的作用就是用來描述欄位的數據類型、方法的參數列表和返回值。而屬性表就是為欄位表和方法表提供額外信息的表結構。對於欄位來說,此處如果將欄位聲明為一個static final msg = "aaa"的常量,則欄位後就會跟著一個屬性表,其中存在一項名為ConstantValue,指向常量池中的一個常量,值為的"aaa"。
方法(methods)
包含訪問標志表, 方法名索引 , 方法描述符索引, 屬性表數量,等
Attribute
0×0001 :同樣的,表示有1個Attributes了。
0x000f : #15(「SourceFile」)
0×0000 0002 attribute_length=2
0×0010 : sourcefile_index = #16(「Demo.java」)
SourceFile屬性用來記錄生成該Class文件的源碼文件名稱。
Ⅵ 什麼是位元組碼文件
位元組碼文件是經過編譯器預處理過的一種文件,是JAVA的執行文件存在形式,
Java源程序(.java)要先編譯成與平台無關的位元組碼文件(.class),然後位元組碼文件再解釋成機器碼運行。解釋是通過Java虛擬機來執行的。
它本身是二進制文件,但是不可以被系統直接執行,而是需要虛擬機解釋執行,由於被預處理過,所以比一般的解釋代碼要快,但是仍然會比系統直接執行的慢。
(6)位元組碼增強編譯期擴展閱讀:
在計算機中,數據只用0和1兩種表現形式,(這里只表示一個數據點,不是數字),一個0或者1佔一個「位」,而系統中規定8個位為一個位元組,用來表示常用的256個字母、符號、控制標記,其中用一個位來進行數據校驗,其他七個位用來記錄數據。
按計算機中的規定,一個英文的字元佔用一個位元組,(如,."':;avcAVC都佔用一個位元組),而一個漢字以及漢字的標點符號、字元都佔用兩個位元組,(如,。「」:;AVCavc他們就得佔用兩個位元組)。
另外,他們是沒有辦法比較的,只能將一個字元佔用一個位元組,N個字元佔用N個位元組。
K是千 M是兆 G是吉咖 T是太拉 8bit(位)=1Byte(位元組) 1024Byte(位元組)=1KB 1024KB=1MB 1024MB=1GB 1024GB=1TB 1024TB=PB 1024PB=1EB 1024EB=1ZB 1024ZB=1YB 1024YB=1BB。
目前最大的計量單位是1BB (Brontobyte)= 1024 YB=10^27。
Ⅶ 請問java中的編譯期和運行期有什麼區別
編譯時是調用檢查你的源程序是否有語法錯誤,如果沒有就將其翻譯成位元組碼文件。即.class文件。
運行時是java虛擬機解釋執行位元組碼文件。
Ⅷ 什麼是位元組碼
位元組碼通常指的是已經經過編譯,但與特定機器碼無關,需要直譯器轉譯後才能成為機器碼的中間代碼。位元組碼通常不像源碼一樣可以讓人閱讀,而是編碼後的數值常量、引用、指令等構成的序列。 位元組碼主要為了實現特定軟體運行和軟體環境、硬體環境無關。位元組碼的實現方式是通過編譯器和虛擬機器。編譯器將源碼編譯成位元組碼,特定平台上的虛擬機器將位元組碼轉譯為可以直接執行的指令。位元組碼的典型應用為Java語言。 位元組碼是一個關於電腦編程語言的小作品。你可以通過編輯或修訂擴充其內容。
Ⅸ hibernate里fetch的問題
19.1. 抓取策略(Fetching strategies)
抓取策略(fetching strategy) 是指:當應用程序需要在(Hibernate實體對象圖的)關聯關系間進行導航的時候, Hibernate如何獲取關聯對象的策略。抓取策略可以在O/R映射的元數據中聲明,也可以在特定的HQL 或條件查詢(Criteria Query)中重載聲明。
Hibernate3 定義了如下幾種抓取策略:
連接抓取(Join fetching) - Hibernate通過 在SELECT語句使用OUTER JOIN(外連接)來 獲得對象的關聯實例或者關聯集合。
查詢抓取(Select fetching) - 另外發送一條 SELECT 語句抓取當前對象的關聯實體或集合。除非你顯式的指定lazy="false"禁止 延遲抓取(lazy fetching),否則只有當你真正訪問關聯關系的時候,才會執行第二條select語句。
子查詢抓取(Subselect fetching) - 另外發送一條SELECT 語句抓取在前面查詢到(或者抓取到)的所有實體對象的關聯集合。除非你顯式的指定lazy="false" 禁止延遲抓取(lazy fetching),否則只有當你真正訪問關聯關系的時候,才會執行第二條select語句。
批量抓取(Batch fetching) - 對查詢抓取的優化方案, 通過指定一個主鍵或外鍵列表,Hibernate使用單條SELECT語句獲取一批對象實例或集合。
Hibernate會區分下列各種情況:
Immediate fetching,立即抓取 - 當宿主被載入時,關聯、集合或屬性被立即抓取。
Lazy collection fetching,延遲集合抓取- 直到應用程序對集合進行了一次操作時,集合才被抓取。(對集合而言這是默認行為。)
"Extra-lazy" collection fetching,"Extra-lazy"集合抓取 -對集合類中的每個元素而言,都是直到需要時才去訪問資料庫。除非絕對必要,Hibernate不會試圖去把整個集合都抓取到內存里來(適用於非常大的集合)。
Proxy fetching,代理抓取 - 對返回單值的關聯而言,當其某個方法被調用,而非對其關鍵字進行get操作時才抓取。
"No-proxy" fetching,非代理抓取 - 對返回單值的關聯而言,當實例變數被訪問的時候進行抓取。與上面的代理抓取相比,這種方法沒有那麼「延遲」得厲害(就算只訪問標識符,也會導致關聯抓取)但是更加透明,因為對應用程序來說,不再看到proxy。這種方法需要在編譯期間進行位元組碼增強操作,因此很少需要用到。
Lazy attribute fetching,屬性延遲載入 - 對屬性或返回單值的關聯而言,當其實例變數被訪問的時候進行抓取。需要編譯期位元組碼強化,因此這一方法很少是必要的。
這里有兩個正交的概念:關聯何時被抓取,以及被如何抓取(會採用什麼樣的SQL語句)。不要混淆它們!我們使用抓取來改善性能。我們使用延遲來定義一些契約,對某特定類的某個脫管的實例,知道有哪些數據是可以使用的。
Ⅹ Java 為什麼要編譯為位元組碼
Java 最初設計的時候,跨平台就是一個重要的目標,所謂「一次編寫,到處運行」。而為了實現跨平台,就決定了不能像 c,c++ 那樣直接把源代碼編譯成可執行文件,因為不同cpu,不同操作系統的指令封裝格式是不一樣的。
而為了實現跨平台,一般有兩種方案,第一是直接執行源代碼,第二是像現在 Java 這樣編譯成一個中間格式文件,即 class 文件,這兩種方案各有優劣,現在說一下編譯成中間代碼的優點,class 文件相比較於 Java 源碼文件,有兩個優點:
class 文件內容設計的更加緊湊,方便 JVM 執行,也方便網路傳輸(最初 JAVA 的一個重要應用就是 applet,在當年網路不是很放大的年代,程序的體積還是要挺重要的)
方便其它語言執行。現在 JVM 上就有除了 Java 外大量的第三方語言,比如 scala,Clojure 等等。其它語言只要編譯成 class 文件即可像 Java 一樣在 JVM 上執行。