<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    應用,一定要應用

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      25 Posts :: 0 Stories :: 118 Comments :: 0 Trackbacks

    #

    2004-08-31

    構建型模式和結構型模式強調的都是靜態(tài)的類實體之間的關系,行為型模式著力解決的是類實體之間的通訊關系。希望以面向對象的方式描述一個控制流程。
    以往的經(jīng)歷中大多是解決類實體的封裝問題,對于類之間的通訊方式上,并沒有刻意的去理解,所以有些行為型模式相對陌生。
    還有一個原因就是行為型模式和面向過程的東西有很多近似之處,導致一定的理解的混淆。
    從筆記就可以看出理解的不夠,可以再專門針對行為型模式做些細節(jié)的學習。

    1 chain of responsibility(職責鏈)-行為型對象模式
    這是個“請求”處理的模式。他提供一個思路,來解決“請求”在一組具有一定結構的類之間傳遞時的問題,所以,我認為這只是一種思路,一種將“請求”象鏈條一樣傳導出去的方式。他的具體傳遞方式,除了和鏈的設計有關之外,最重要的是和對象組的結構有關。
    當然,如果沒有結構的對象組,我們也可以強行的動態(tài)構建一個鏈,這種方式雖然復雜和略土,但肯定更加的靈活,不僅能控制處理,還能控制鏈的走向。

    一般來看,composite模式和這種模式經(jīng)常在一起,Microsoft IE中的文檔事件模型應該采用的就是這樣的模式。

    2 command(命令)-行為型對象模式
    將請求封裝為一個對象,從而可以對請求做一些統(tǒng)一性處理,如:排隊、日志、撤銷等。
    適用性:
    1、是回調機制的一個面向對象的替代品
    2、在不同時期指定、排列、和執(zhí)行請求
    3、支持取消操作,但是,此處對象的狀態(tài)存儲是個麻煩的東西。
    4、支持原語操作上構建高層操作的系統(tǒng)。這種在支持“事務”的系統(tǒng)中很常見。
    理解還是不很透徹

    3、Iterator(迭代器)-行為型對象模式
    將聚合類的遍歷算法封裝為Iterator,從而封裝對象的內(nèi)部表示。
    Iterator分為外部和內(nèi)部,外部更加靈活,內(nèi)部傳入?yún)?shù)簡單(只需要操作),內(nèi)部Iterator自動遍歷所有元素。
    Iterator可以封裝算法,也可以只記錄狀態(tài),由聚合類封裝算法,封裝算法的iterator可能會破壞聚合類的封裝性。

    4、mediator(中介者)
    mediator希望通過一個中控對象來完成對多個對象的關系的管理。
    將多數(shù)可以可以重用的組件無關聯(lián)的構建起來,而他們之間的關系由額外的對象來完成。
    在圖形化編程里,可以用此模式和listener機制(observer模式)結合使用,更加方便,進一步解除了中控對象與其他對象的耦合。

    5、memento(備忘錄)/token
    原發(fā)器(originator)(需要保存狀態(tài)的)申請一個備忘錄(memento),并自己將狀態(tài)保存進去,然后,將備忘錄交給管理者(caretaker),當出現(xiàn)需要的時候,管理者將合適的備忘錄交給原發(fā)器,原發(fā)器自己恢復自己的
    狀態(tài)。
    memento模式,從originator中分離了保存客戶請求狀態(tài)的過程。并且memento的存儲和解釋都是由originator完成,保證了封裝的邊界。
    如果備忘錄的創(chuàng)建及其返回(給原發(fā)器)的順序是可預測的,備忘錄可以存儲增量改變。

    6、observer(觀察者)/依賴(dependents)/發(fā)布-訂閱(Publish-Subject)
    suject(目標)和observer(觀察者)是關鍵對象,suject和不固定的observer發(fā)生關系,將這種關系解耦是這個模式的主要功能,listener機制可以看作這種模式的一個實現(xiàn),當然mvc也是這種模式的一個好的應用場景。
    與mediator的區(qū)別主要體現(xiàn)在,observer是一個對關聯(lián)關系的解耦過程,而mediator更加注重各個對象執(zhí)行的功能。

    7、state(狀態(tài))/狀態(tài)對象(Objects for Status)
    允許一個對象在改變其狀態(tài)的時候改變它的行為,使得對象似乎修改了自己的類。
    1、將狀態(tài)相關的行為局部化。
    2、狀態(tài)轉換顯式化

    我們可以根據(jù)當前窗口的狀態(tài)來轉變窗口的菜單和操作,這種方式可以用state模式來實現(xiàn)。

    8、strategy(策略)
    將算法單獨的封裝起來,使得它獨立于其他對象的變化。
    其實這種方式和面向過程里的一個算法函數(shù)封裝基本是一樣的,只是由于封裝成為了類,會有一些接口統(tǒng)一的便于替換的特性。

    9、visitor(訪問者)
    這種模式的主要目的是分離操作和對象,追求的是對象的重用和簡單,以及操作的可替代性。
    相對來說,strategy模式更加追求的是封裝操作,追求操作的重用性。
    observer、mediator追求分離對象之間的關系與對象本身。


    以上都是對象級別的行為模式,以下是類級別的行為模式
    1、template(模板)
    定義一個算法的骨架,并將其中一些步驟延遲到子類中。
    這種使用較多,不多說了。

    2、interpreter(解釋器)
    本模式描述了如何為簡單的語言定義一個文法,如何在該語言中表示一個句子,以及如何解釋這些句子。
    這種方式在正則表達式中比較明顯,在以往的程序應用中,特別是上層應用中很少用到。
    expression::= literal | alternation | sequence | repetition | '(' expression ')'
    alternation ::= expression '|' expression
    sequence ::= expression '&' expression
    repetition ::= expression '*'
    literal ::= 'a'|'b'|...{'a'|'b'|...}*

    相關的關鍵參與者為:
    1、abstractExpression(抽象表達式,統(tǒng)一的接口)
    2、terminalExpression(終結符表達式)
    3、nonterminalExpression(非終結符表達式)

    posted @ 2006-08-24 17:10 flyffa 閱讀(1178) | 評論 (0)編輯 收藏

    2004-08-30

    結構型模式:描述的是一系列將類和對象進行組合,以構建更大的類和對象。其強調的是結構化的方式,而不是怎樣去構造這些類。

    結構型模式分為兩種:
    a、結構型類模式:通過接口或類的繼承來實現(xiàn)。
    b、結構型對象模式:不是對類或接口,而是對對象進行組合。

    /*****************************************************************************************/
    1、Adapter(適配器)/wrapper(包裝器)
    適配模式最重要的作用是去將已有的、但是接口不兼容的東西接入到系統(tǒng)中來。進行復雜邏輯程序的有效重用。
    這個模式中adaptor,adaptee的基類是具有惟一性的。

    a、類適配
    類適配就是通過繼承這種靜態(tài)的方式來進行適配,也就是適配器會繼承需要被適配的東西,
    缺點是適配的范圍比較小,不能滿足同時適配一組對象(類及其子類)的要求。

    b、對象適配
    對象適配:適配器并不會靜態(tài)的繼承,而會是采用引用需要被適配類的方式,這樣,被適配類及其子類都可以被適配了,
    缺點:需要動態(tài)的指定被適配對象,而且容易引起運行期錯誤


    注:可能是對于其他面向對象語言的不了解,我覺得用對象適配就可以了,沒有必要使用類適配的模式,對于只有一個需要適配的類的情況,我們只需要將動態(tài)構造引用對象的過程加在適配器的構造函數(shù)中就可以了,在今后對其他類型的OO語言有了了解之后,可以再回顧一下此處。


    /*****************************************************************************************/
    2、bridge(橋接)/(Handle/boby)---結構型對象模式
    橋接的模式最重要的作用是將抽象/表現(xiàn)與實現(xiàn)相分離,保持程序良好的可擴展性。
    這個模式中window和windowimpl這兩個接口是具有惟一性的。

    一個一般的繼承模式的設計
    window--xwindow
    ?pmwindow
    ?iconwindow--pmiconwindow
    ????? xiconwindow
    這種樹狀的繼承方式將抽象的表現(xiàn)部分iconwindow和抽象的實現(xiàn)部分(xwindow,pmwindow)集成到了一起。
    而這兩者其實負責不同的東西,一是表現(xiàn)(外部特征,如icon是可以拖拽的,是由矩形組成的等等),二是具體實現(xiàn)平臺,負責在xwindow風格下的線如何畫,線有多粗,從什么位置開始畫等等。

    于是應該有著兩條線的結構:
    window--iconwindow
    ?applicationwindow

    windowimpl--xwindow
    ???? pmwindow

    中間通過window對windowimpl的引用來達到橋接的作用,也就是說,橋接的奧秘就在于此,合理的將這兩者的接口進行分離,是橋接模式設計的關鍵。

    橋接方式的退化形式就是我們只是需要實現(xiàn)xwindow或者pmwindow中的一種,這樣windowimpl就失去意義了。(對于有些語言,windowimpl的存在可能有利于實現(xiàn)的改變不需要重新編譯客戶應用程序)??

    /*****************************************************************************************/
    3、composite(組合)---結構型對象模式
    組合模式使得單個對象和組合對象的使用具有一致性。使得對外提供的接口變得單一,用戶忽略單個對象與組合對象的差異。
    組合模式著力于解決這樣一個矛盾:
    在一個程序組中有著層次的關系,需要表現(xiàn)(這是一個內(nèi)部重用性和易讀性的問題)
    但是這個程序組中的對象有著共性,并且希望外部調用程序忽視其各異性而只是關注其共性的部分(這是一個外部接口簡單化的問題)。
    所以其主要元素的關系就是這樣了:

    composite(復合對象)-leaf(簡單對象)
    ????? composite(復合對象)-leaf(簡單對象)
    ?????leaf(簡單對象)

    而這些對象實現(xiàn)統(tǒng)一的接口或者抽象類:compositeInterface;任何client對任何對象實例的操作都是通過接口進行。

    模式的實現(xiàn):
    在實現(xiàn)中會有一系列的問題,這只是實現(xiàn)的問題,和模式本身無關。
    1、顯示父對象引用:解決方法:建立一個穩(wěn)定,模式化的父子引用關系和操作方法。
    2、共享組件:這將父子之間的1:N的關系變成了N:N的模式,參考flyweight模式。
    3、最大化component接口:這是保證操作透明化的必須,我們應該盡力達到這個目的。
    4、聲明管理子部件的操作:這個問題最大的麻煩來源于子部件和父部件最大的差異--有沒有子節(jié)點,可以通過統(tǒng)一的,技巧性的add,remove方法來完成。
    5、compositeInterface是否應該實現(xiàn)一個compositeInterface列表:這是一個關于存儲的問題,就是對于子節(jié)點的引用對于葉子節(jié)點是無意義的內(nèi)存消耗。
    6、子部件排序:Iterator模式應該有一定的作用。
    7、高速緩存改善性能。


    /*****************************************************************************************/
    4、decorator(裝飾)/包裝器(wrapper)---結構型對象模式
    從名字我們就可以看出這個模式的基本立意:一位畫家畫完一幅畫(實現(xiàn)一個組件)之后,并不需要自己去做畫框(decorator),做這個畫框就是這個模式需要解決的問題。
    可以看到畫框能為畫家所用是基于一種前提的,就是畫家的用紙和畫框的大小是符合的,也是基于一種結果,就是畫還是畫,不會因為畫框而改變其畫的本質和內(nèi)容,只是現(xiàn)在是一幅有框的畫了。
    回到模式中,我們可以看到這個模式的大概了:

    component(組件接口)-concreteComponent(組件實現(xiàn))
    ???? -decorator(裝飾器)-->m_cmp(對組件實現(xiàn)的引用)

    這里我們可以看到decorator模式和adaptor模式的區(qū)別,decorator著力于裝飾器部分的重用,而adaptor只是著力于組件的重用。decorator著力于封裝組件的可以插件化的共性特征,其著眼點是組件級別以下的功能重用。adaptor著眼的還是組件一級的功能重用。

    /*****************************************************************************************/
    在前面的composite和decorator模式中,我們不停的追求將組件實現(xiàn)得更加的細粒度化,以便增加組件的可重用性,這基本是各種良好設計的共同特征。
    但是這種設計方式也會導致各種問題,其中就包括零散、以及大量對象實例導致的資源消耗問題。
    /*****************************************************************************************/
    5、facade(外觀)--結構型對象模式
    facade模式最大的特點就是將復雜、零散的子系統(tǒng)進行唯一入口的封裝。
    這種模式在我經(jīng)歷的系統(tǒng)印象最深的就是多層分層的層層之間的接口上,一個唯一的入口,讓層次非常的清晰。

    其實這種模式與adaptor有一定的相似之處,都是屏蔽兩個不同的子系統(tǒng),但是不同的是,facade是主動的構建,而adaptor是為了接入其他的系統(tǒng)而被動的構建的,可以看出,要對一個已經(jīng)實現(xiàn)了facade模式的子系統(tǒng)構建adaptor遠比沒有沒有實現(xiàn)facade模式的要簡單的多,代價要小得多。

    /*****************************************************************************************/
    6、flyweight(享元)--結構型對象模式
    享元設計模式著力解決的就是當內(nèi)存中存在大量同樣的對象實例導致的資源消耗問題。
    可以幾個方面來理解,
    享元模式追求的是實例級別的重用。
    將外部狀態(tài)(上下文)和對象實例本身分離,不是在構建時傳入外部狀態(tài),而是在運行期,甚至這種狀態(tài)完全是過程性的,和對象實例沒有關系。而內(nèi)部狀態(tài)只在創(chuàng)建時指定,而在運行期是絕對不可以碰的。

    這種模式與原型模式的最大區(qū)別在于,一個共享實例級別的,一個是共享類的級別。

    /*****************************************************************************************/
    6、proxy(代理)/surrogate--結構型對象模式
    常見使用情況
    1、遠程代理(remote proxy)
    2、虛代理(virtual proxy):根據(jù)需要創(chuàng)建開銷很大的對象。
    3、保護代理(protection proxy):控制對原始對象的訪問。
    4、智能指引(smart refrence):取代簡單指針,便于在訪問對象前做些附加操作。
    這種代理使用廣泛,什么copy_on_write,lazy_loading等技術都可以考慮這種方式的實現(xiàn)。

    proxy模式代理和被代理對象接口是一致的或者是子集,但adaptor模式則不同。
    decorator模式為對象增加接口,而proxy是轉發(fā)或者限制接口。

    posted @ 2006-08-24 17:09 flyffa 閱讀(1096) | 評論 (0)編輯 收藏

    2004-05-25

    每次看設計模式這本書的時候都有著相同的感覺,上次沒有真的理解,這次才是理解了,但是還差那么一點點。
    人其實挺奇怪的,這些模式在編程的幾年之內(nèi),無論是具體的項目中還是自己的練習中,都使用了很多,只是沒有作為一種模式總結出來而已,而是以經(jīng)驗的形式存在于腦海之中,隨意的使用,隨意的忘卻。
    可能就是必然的學習過程吧,隨意使用--形成模式--突破模式靈活應用。而模式在這里起著把經(jīng)驗持久化的作用吧,減少忘卻的可能。
    所以,真正的掌握模式,除了需要理解模式的表現(xiàn)之外,需要理解模式著力解決的問題,理解模式的缺陷和優(yōu)勢,才能做到最終靈活抽取各個模式之長而靈活組合之,這可能就是我在模式領域追求的無招勝有招的境界吧。

    模式的核心目的大多是兩種之一:重用和解耦

    言歸正傳,還是來說說具體的模式吧:Design patterns


    模式分類:構建型模式
    模式一:抽象工廠(Abstract Factory)
    Factory理解為對象工廠的概念,用以生成一個系列的對象組。
    而Abstract Factory就是基于Factory之上的概念,目的是把多個系列的對象組抽取共性,屏蔽不同系列之間的對象的差異。

    ?系列???? motif?????? windows?
    對象組
    Button??? motifBtn??? wBtn
    Bar?????? motifBar????wBar
    Textbox?? motifTB???? wTB

    class abstractFactory{
    ?Button getButton();
    ?Bar getBar();
    ?Textbox getTextbox();
    }


    button,bar,textbox是一組對象,而我們需要實現(xiàn)motif,windows等不同系列風格的對象組,Abstract Factory提供的方式下,我們對于大多應用程序而言,操作的口是abstractFactory,以及Button,Bar,Textbox這些對象組,而無需具體關心是motif風格還是windows風格的,風格系列的指定只決定于實現(xiàn)abstractFactory的具體工廠類。

    這種方法便于這種系列的增加,但是并不有利于對象組成員的增加,比如要增加一個label對象,我們就需要增加一個抽象對象Lable,還需要修改abstractFactory以及他所有的子類。

    所以使用這種方法的時候,最重要的是對象組的規(guī)劃設計。


    模式二:生成器(builder)
    生成器的概念是提供一系列的方法生成對象的不同部分,最終返回一個完整的對象,著力于解決將構造方法和構造步驟分離的問題,builder內(nèi)部封裝的是構建方法而不是過程。
    做了這樣的分離之后,再將builder做一個抽象,從而使得不同的構建方法和構建過程做到分離。

    假設一個串的存儲管理:
    class builder(){
    ?add(key,value);
    ?addStr(str);
    }

    同樣的操作集合,
    add(key,value),addStr(str)
    對于不同的builder,可能輸出的結果就會有多種:
    key=value;str

    另一種可能:

    ?value
    ?str

    模式三:工廠方法(Factory)
    其實他的另一個名字更加能夠說明問題(虛構造)
    也就是說通過抽象類的共同方法來避免構造時的硬編碼,
    如:button對象有個getBtn的方法,
    就可以避免寫出button btn = new motifButton();這樣的代碼,而將這樣的代碼封裝到了子類自身。


    模式四:原型法(prototype)
    就是在應用時并不是創(chuàng)建一個新的對象,而是從已有的對象中拷貝一個。
    這種方式我在做配置池的時候用到過,每個業(yè)務程序從我的池中去拷貝一個對象,然后才進行相關的修改和應
    用。
    這種方式同樣是動態(tài)創(chuàng)建類的方法,著重于解決當對象組的成員不穩(wěn)定的情況,而不是多個系列的問題。

    與Factory相比,他并不是每一個原型都需要一個構建子類。
    缺點:clone本身實現(xiàn)的難度。

    模式五:單件(singleton)
    這種模式使用無數(shù),就不再多說了。用于保證實例的唯一性。

    posted @ 2006-08-24 17:08 flyffa 閱讀(921) | 評論 (0)編輯 收藏

    2004-10-25

    第八章線程和鎖
    這章描述的是非常底層的jvm運作的時候的概念上的部分模型,與前部分的編譯不屬于一個層次。
    本章提到的變量概念是指類實例,類變量,和類數(shù)組。而參數(shù)和局部變量并不強行要求到這個變量概念之中。
    8。1術語和框架
    jvm中有主寄存器,當一個線程被啟動時,會創(chuàng)建自己的工作寄存器,當線程運行,會對主寄存器中的數(shù)據(jù)進行拷貝,存入自己的工作寄存器中。
    主寄存器包含每個變量的主拷貝。
    主寄存器也包含鎖,每個對象有個與其相關的鎖。線程可以競爭獲得一個鎖。
    相關術語:
    use,assign,load,store,lock,unlock為線程可以執(zhí)行的動作。
    read,write,lock,unlock為主存儲器子系統(tǒng)可以執(zhí)行的動作。
    use,assign是線程執(zhí)行引擎與工作存儲之間的緊密耦合交互作用。
    lock,unlock是線程執(zhí)行引擎與主存儲之間的緊密耦合交互作用。
    主存儲與工作存儲之間卻是松散耦合的。
    分別對應的動作就是:load,store和lock,unlock

    注意有三個實體在協(xié)同工作:主存儲器,工作存儲器,線程運行引擎

    8。2執(zhí)行順序和一致性。
    1。同線程執(zhí)行動作排序
    2、主存儲執(zhí)行的、對同一變量的動作排序
    3、主存儲執(zhí)行的、對同一鎖的動作排序
    4、不允許一個動作跟在其自身后面。

    第4點特殊說明:雖然看起來無關緊要,但必須顯式說明,以保證完整性。因為這種危險確實存在。

    線程的動作和主存儲的動作間的約束:
    1、每個lock和unlock動作必須由一些線程和主存儲共同執(zhí)行。
    2、每個load動作,唯一的與一個write動作配對,這樣write動作跟在store動作后。

    8。3有關變量的規(guī)則

    線程T對變量V的操作約束:
    1、T執(zhí)行過程中只有需要相應使用V時才調用use,或者assign動作。
    2、T執(zhí)行的assign動作必須插入到T對V的load或者store和后繼的由T執(zhí)行的對V的store之間。(保證主存儲內(nèi)值的正確,同時保證assign動作之前工作存儲內(nèi)存在V)
    3、在T對V執(zhí)行use和store之前,必須執(zhí)行assign或load操作(保證工作存儲器中有V,并且已經(jīng)初始化)
    4、在V創(chuàng)建后,每個T在use或store之前,必須執(zhí)行assign或load操作。

    對于第4點:volatile(易變)變量有更嚴格的約束

    由主存儲器執(zhí)行的read和right操作的約束:
    1、T對V的load,必須先有對應的read
    2、T對V的store,必須后繼對應的write
    3、動作A,B是T對V的load或store動作,P,Q為對應的read或write,如果A優(yōu)先于B,則P必須有些于Q
    ?
    8.4Double和long變量的非原子處理
    由于32位機器的效率問題,有些jvm實現(xiàn)對double和long這種64位值操作是非原子的,導致一些同步問題(如程序員總是需要顯式指定同步于對double和long上的操作),其實這只是一種軟件設計對硬件的妥協(xié)而已。

    8。5有關鎖的規(guī)則
    線程為T,鎖為L,T執(zhí)行的關于L的操作約束如下:
    1、T對L的lock操作,必須對于每個不是T的線程S,S對L的unlock操作數(shù)等于之前的S對L的lock操作數(shù)
    2、T對L的unlock操作,必須要求先前T對L的unlock操作數(shù),小于先前T對L的lock操作數(shù)(不解不擁有的鎖)

    8。6有關鎖和變量交互作用的規(guī)則
    線程T,鎖L,變量V,T執(zhí)行的關于L和V的操作約束如下:
    1、在t對V的assign和隨后的unlock之間,必須插入store操作。對應于該store的write操作必須先于unlock操作(保證L對于V的有效性)。
    2、在lock和隨后執(zhí)行的use或store之間,必須插入assign或load操作。

    8。7有關volatile(易變)變量的規(guī)則
    線程T,易變變量V和W
    1、load和use操作必須成對出現(xiàn),緊挨在一起,并且load操作在前
    2、assign和store操作必須成對出現(xiàn),緊挨在一起,并且assign操作在前
    3、A、B為T對V的use或assign,F、G為對應的load或store,P、Q為對應的read或write,如果A先于B,則P必須優(yōu)先于Q。

    8。8先見存儲操作
    如果變量沒有聲明為violate,則store操作可以提前于assign,store操作將將要賦給V的值替代V實際的值進行store操作,只要滿足:
    1、如果發(fā)生store,必然發(fā)生assign。
    2、重定位的store和assign間未插入鎖定操作。
    3、重定位的store和assign間未插入對V的load
    4、重定位的store和assign間未插入其他對V的store
    5、store操作將assign操作要放到線程T的Z作為存儲器中的值傳到主存儲器。

    8。9討論

    8。10可能的交換
    一個關于同步和鎖的小例子。

    8。11范例:無序寫
    另一個例子

    8。12線程
    線程由Thread和ThreadGroup類創(chuàng)建并管理。創(chuàng)建Thread對象就創(chuàng)建一個線程,而且是創(chuàng)建線程的唯一方式。當線程被創(chuàng)建時,它還不是活躍的,當其start方法被調用時,開始運行。

    8。13鎖和同步
    每個對象都有與其關聯(lián)的鎖。
    當synchronized方法被調用時,它自動執(zhí)行鎖定操作;如果該方法是實例方法,它鎖定同實例相關聯(lián)的鎖,如果方法是static的,它鎖定同Class對象相關聯(lián)的鎖

    8。13等待集和通知
    每個對象除了相關的鎖外,還有相關的等待集,即一組線程,首次創(chuàng)建的對象,等待集為空。
    講述了wait,notify,notifyall幾個方法,wait方法往等待集中增加內(nèi)容,而notify或notifyall方法從等待集中刪除內(nèi)容。
    但不能完全讀懂內(nèi)容,可細研究。

    第九章優(yōu)化
    本章描述jvm中Sun版本中實現(xiàn)的優(yōu)化。
    在此優(yōu)化中,編譯的jvm代碼在運行期修改,利用運行期獲得的信息,做比源指令更少的工作,以獲得更好的性能。

    9。1通過重寫動態(tài)鏈接
    對重寫的指令,指令的每個實例在其第一次執(zhí)行時被替換為_quick偽指令,該指令實例隨后執(zhí)行的總是_quick變體。
    其余是對_quick偽指令的描述,可用于查閱,因為這是Sun的jdk在運行的時候的真正指令狀態(tài)。

    第十章 操作碼的操作碼助記符
    這章主要是個附錄的功能,可供查閱。


    ×××××××××××××××××××××××××××××××××××
    在延期了將近一個月了之后,終于算是看過了一遍這本書,雖然有很多沒有看的非常明白的地方,但是比我預期的效果要好了許多了,進一步的細致研究可以安排在后面。

    posted @ 2006-08-24 17:07 flyffa 閱讀(1325) | 評論 (0)編輯 收藏

    2004-10-24

    i=0;i=i++為什么等于0這個問題困擾了我好長的一段時間,結果前段時間還試圖從虛擬機那個層面進行解釋,但無論是線程還是方法調用都不能解釋其現(xiàn)象,發(fā)現(xiàn)方向性錯誤,這只是一個語言的特性而已。在java lang spec中提到:
    1、java運算符的優(yōu)先級++符是大于=的。
    2、The result of the postfix increment expression is not a variable, but a value.后++符表達式的結果是個值而不是一個變量。

    也就是說后++符先將自己的值存儲起來,然后對變量進行++;
    再進行賦值操作,也就是將先存儲起來的值賦給變量i,這樣的操作就導致了i值被置為0了


    對于C和C++來說不一樣,在講到m=i++操作時,C語言是先將i的值賦給了m,然后將i值++,這樣i=i++的結果自然就是1了,c的實現(xiàn)中是不存在那個中間的值的存儲的。


    由于java和c不同的語言特性,導致了i=i++的不同之處,前面的筆記中已經(jīng)提到,由于java lang spec中的一些細微規(guī)定,導致其運行結果的不同,我們可以用個例子來看i=i++在jvm中實際的運行過程。
    源程序test.java:
    public class test {
    ? public test() {
    ? }
    ? public static void main(String[] args) {
    ??? int i=0;
    ??? i=i++;
    ? }

    }
    我們用javap來看其實際的虛擬機指令集:
    C:\JBuilderX\jdk1.4\bin>javap -c? -classpath "d:/" test
    Compiled from "test.java"
    public class test extends java.lang.Object{
    public test();
    ? Code:
    ?? 0:?? aload_0
    ?? 1:?? invokespecial?? #1; //Method java/lang/Object."":()V
    ?? 4:?? nop
    ?? 5:?? return

    public static void main(java.lang.String[]);
    ? Code:
    ?? 0:?? iconst_0?//常數(shù)0入棧
    ?? 1:?? istore_1?//i賦值,常數(shù)值出棧
    ?//至此完成i=0;
    ?? 2:?? iload_1??//裝載變量i,0入棧
    ?//第2步是特殊的一步,這步將i值先行保存,以備賦值使用
    ?? 3:?? iinc??? 1, 1?//變量值增加,棧內(nèi)值不變
    ?//至此完成i++
    ?? 6:?? istore_1?//i賦值,0出棧。
    ?//至此完成i=i++
    ?? 7:?? nop??//donothing
    ?? 8:?? return

    }

    對比而言,對于i++而言,i=i++指令多了兩步,2和6
    其實這兩步是賦值符號引起的,有意思的是第二步出現(xiàn)的時機,是在iinc之前,這就是因為java lang spec中規(guī)定的。

    posted @ 2006-08-24 17:05 flyffa 閱讀(968) | 評論 (0)編輯 收藏

    2004-10-22

    第四章:class文件格式
    java.io.DataInput和java.io.Output輸入輸出的都是以高端字節(jié)序輸出字節(jié)。
    與C結構的域不同,class文件中連續(xù)的項順序存儲,不進行填充或者對齊。
    4.1classFile
    一個class文件包含一個單獨的classFile結構,包含:
    一個四字節(jié)的幻數(shù)表明class類型。具有值0XCAFEBABE;
    access_flag用于表明是類還是接口,是abstract,final還是其他
    另外分別有表存儲:常量、屬性、方法、域。
    目前屬性只有sourceFile屬性。
    4。2完全限定類名稱的內(nèi)部形式
    出現(xiàn)在classFile文件結構中的類都以完全限定類名稱的方式出現(xiàn),并且不是類似于java.lang.xxx,而是變?yōu)閖ava/lang/xxx
    4.3描述符
    域類型有:根類型,對象類型,數(shù)組類型
    根類型有:B,C,D,F,I,J,S,Z
    對象類型:L
    數(shù)組類型:[
    多維數(shù)組double[][][] d的表示方式:[[[D
    方法返回描述符
    V表示void

    object mymethod(int i,double j,Thread t)的方法描述符為:
    (IDLjava/lang/Thread;)Ljava/lang/Object;
    java的方法不管是static還是實例方法描述符都是如此,區(qū)別在于jvm運行時給實例方法隱式的傳遞當前對象的指針this

    4.4常數(shù)池
    常數(shù)池由一組類似于cp_info的結構構成
    cp_info{
    ?u1 tag;
    ?u1 info[];
    }

    4.5域
    每個域由一個變長的field_info構成
    field_info{
    ?u2 access_flags;
    ?u2 name_index;
    ?u2 descriptor_index;
    ?u2 attribute_count;
    ?attribute_info attributes[attributes_count];
    }

    4.6方法
    每個方法由變長結構method_info構成
    method_info{
    ?u2 access_flags;
    ?u2 name_index;
    ?u2 descriptor_index;
    ?u2 attribute_count;
    ?attribute_info attributes[attributes_count];
    }

    4.7屬性
    屬性用于field_info,method_info,class_file結構之中,結構一般如下:
    attribute_info{
    ?u2 attribute_name_index;
    ?u4 attribute_length;
    ?u1 info[attribute_length];
    }

    某些屬性被預定義作為class文件規(guī)范的一部分,這些屬性是:sourceFile,ConstantValue,code,exception,lineNumberTable和localVariableTable屬性。

    4。8對java虛擬機代碼的約束

    4。9class文件的檢驗

    4。10java虛擬機和class文件格式的限制

    posted @ 2006-08-24 17:03 flyffa 閱讀(1286) | 評論 (0)編輯 收藏

    2004-09-30

    第六章:jvm虛擬指令集
    6.1假定:“必須”的含義
    對于jvm指令的一些“必須”的要求,在運行期要求javaclass的結構是滿足約束的,對于不滿足約束的情況,jvm的行為是未定義的。
    6.2保留操作碼
    在java class文件中使用的指令操作碼,有三個操作碼是保留的,供java虛擬機內(nèi)部使用。
    254(0xfe)和255(0xff),分別有助記符impdep1和impdep2,目的是在軟件或者硬件實現(xiàn)的特定功能提供“后門”或陷阱。
    202(0xca),有助記符breakpoint,目的是由調試程序使用來實現(xiàn)斷點。

    6.3虛擬機錯誤
    當內(nèi)部錯誤或者資源限制導致java語言語義不能實現(xiàn)時,jvm拋出一個VirtualMachineError類的子類的實例。jvm規(guī)范不規(guī)定和語言拋出的時間和地點。

    6.4jvm指令集
    我不一一例舉各種指令的操作碼和用法,需要時去查就行了。

    第七章 為jvm編譯
    7.1范例格式
    java編譯成為class文件之后,以類匯編的jvm操作指令方式存在,jdk自帶的javap程序具有這樣的功能,將class文件翻譯為這樣的指令集。
    下面是我測試的一個實例:
    源文件為test.java
    public class test {
    ??? public static String a = "";
    ??? public int i =0;
    ??? public test() {
    ??????? int i=0;
    ??????? String a = "xyz";
    ??? }

    }
    編譯完成為test.class,用javap生成之后輸出結果為:
    C:\JBuilderX\jdk1.4\bin>javap -c? -classpath "c:/" test
    Compiled from "test.java"
    public class test extends java.lang.Object{
    public static java.lang.String a;

    public int i;

    static {};
    ? Code:
    ?? 0:?? ldc???? #4; //String
    ?? 2:?? putstatic?????? #5; //Field a:Ljava/lang/String;
    ?? 5:?? nop
    ?? 6:?? return

    public test();
    ? Code:
    ?? 0:?? aload_0
    ?? 1:?? invokespecial?? #1; //Method java/lang/Object."":()V
    ?? 4:?? aload_0
    ?? 5:?? iconst_0
    ?? 6:?? putfield??????? #2; //Field i:I
    ?? 9:?? iconst_0
    ?? 10:? istore_1
    ?? 11:? ldc???? #3; //String xyz
    ?? 13:? astore_2
    ?? 14:? nop
    ?? 15:? return

    }

    7.2常數(shù)、局部變量和控制結構的使用
    jvm是面向棧的,大多數(shù)操作都是從當前框架的操作數(shù)棧中取得操作數(shù)。

    7。3運算
    jvm一般在操作數(shù)棧上進行運算,即從棧中取操作數(shù),并將結果存入操作數(shù)棧中。

    7。4訪問常數(shù)池
    byte,char,short,以及小int值都可以通過立即數(shù)的方式編譯在method的code中,但是int,long,float,double,以及string實例的引用,就需要對常數(shù)池進行訪問了。使用ldc,ldc_w,ldc2_w指令管理。

    7.5更多控制范例
    可供查閱

    7。6接收參數(shù)
    如果向java實例方法傳遞了n個參數(shù),它們被接收,按約定,框架的編號1到n的局部變量為新的方法調用創(chuàng)建,順序為接收的順序。
    7。7調用方法
    對java實例方法的調用,是在對象的運行期類型上調度的。用invokevirtual實現(xiàn),將其參數(shù)取做對常數(shù)池表項的索引,給出對象的類類型的完整限定符名稱,再調用方法的名稱和方法的描述符。

    對java靜態(tài)(類)方法的調用,無需傳遞類實例,其余和實例方法相似,用invokespecial方法實現(xiàn)。

    invokespecail指令用于調用實例初始化方法。超類方法和調用private方法。

    7。8處理類實例
    構建一個類實例的過程,在建立對象及其實例域之后,用invokespecial調用相應構造函數(shù)對應的方法來初始化對象。
    對對象域的訪問用getfield和putfield指令完成。

    7。9數(shù)組
    主要講的是數(shù)組操作的相關jvm指令,如:newarray,過一遍,可以查閱。

    7。10編譯開關
    對于java的switch指令,jvm有對應的兩種指令:tableswitch,lookupswitch.
    tableswitch指定取值范圍,而lookupswitch并不指定取值范圍,兩者如何選擇完全由效率選擇決定。

    7。11對操作數(shù)棧的操作
    jvm有大量的指令補充,將操作數(shù)棧的內(nèi)容作為無類型字或成對的無類型字操縱。便于jvm虛擬機指令的靈活組成。
    如dup,dup_x2等,都是對字或者雙字進行操作。

    7。12拋出或者處理異常
    jvm中try...catch塊的處理對于jvm指令處理是透明的,輔助控制是由異常表來完成的,由異常表來決定到哪里去調用處理,哪些部分的異常是受控的。

    7。13編譯finally
    try.....finally語句與try-catch相似,只是其輔助控制是由指令jsr(子例程調用)顯式的表示,在jsr調用之前,將下一指令的地址壓入棧中。而異常表只控制try塊的范圍。

    7。14同步
    jvm用monitorenter和monitorexit指令對同步提供顯式支持。而java常用sychronized方法。
    sychronized“方法”通常不是用monitorenter和monitorexit指令實現(xiàn)的。往往是由“方法調用指令”檢查常數(shù)池里的ACC_SYCHRONIZED標志
    但monitorenter和monitorexit指令是為了支持sychronized“語句”而存在的。
    注意這里的方法和語句的區(qū)別。

    語句實例如下:test.java
    public class test {
    ? public test() {
    ? }
    ? public static void main(String[] args) {
    ??? synchronized(new Object()){
    ??????? int i = 0;
    ??? }
    ? }

    }
    編譯完的結果:
    C:\JBuilderX\bin>javap -c? -classpath "d:/epm40/classes" test
    Compiled from "test.java"
    public class test extends java.lang.Object{
    public test();
    ? Code:
    ?? 0:?? aload_0
    ?? 1:?? invokespecial?? #1; //Method java/lang/Object."":()V
    ?? 4:?? nop
    ?? 5:?? return

    public static void main(java.lang.String[]);
    ? Code:
    ?? 0:?? new???? #2; //class Object
    ?? 3:?? dup
    ?? 4:?? invokespecial?? #1; //Method java/lang/Object."":()V
    ?? 7:?? dup
    ?? 8:?? astore_1
    ?? 9:?? monitorenter
    ?? 10:? iconst_0
    ?? 11:? istore_2
    ?? 12:? nop
    ?? 13:? aload_1
    ?? 14:? monitorexit
    ?? 15:? goto??? 23
    ?? 18:? astore_3
    ?? 19:? aload_1
    ?? 20:? monitorexit
    ?? 21:? aload_3
    ?? 22:? athrow
    ?? 23:? nop
    ?? 24:? return
    ? Exception table:
    ?? from?? to? target type
    ??? 10??? 15??? 18?? any
    ??? 18??? 21??? 18?? any

    }

    而synchronized方法編譯沒有特殊之處,只是在方法名上加了synchronzied字樣。

    posted @ 2006-08-24 17:02 flyffa 閱讀(2808) | 評論 (0)編輯 收藏

    2004-09-27

    第三章:jvm結構
    3.1數(shù)據(jù)類型
    基本類型和引用類型
    基本值和引用值

    數(shù)據(jù)不需要做標記或者可被檢查以確定類型。也就導致jvm的指令集是針對特定類型的值的。

    jvm包含對對象的顯式支持(引用類型)

    3.2基本類型和值
    基本類型--returnAddress類型(jvm指令的操作碼的指針,不是java類型)
    ?--數(shù)值類型--整型--byte
    ???--short
    ???--int
    ???--long
    ??? --浮點型--float
    ???? --double
    ???--char

    jvm中沒有boolean類型,java中的boolean類型的操作被翻譯為int類型進行操作。


    問題:在數(shù)值類型中提及的NaN值對應于java里的什么情況

    3.3引用類型和值
    有三種引用類型:類類型,接口類型,數(shù)組類型

    3.4字
    jvm中沒有指定數(shù)據(jù)類型的存儲器大小,只是指定了一個“字”的概念,一個字足以持有byte,int,char,short,float,returnAddress,refrence的值,兩個字足夠大持有double,long的值。

    一般來說,一個字的大小是主機平臺的一個指針的大小,32位機上,字是32位,64位機上,字是64位的,但這是實現(xiàn)決定的,而不是jvm規(guī)范決定的。

    3.5運行期數(shù)據(jù)
    pc(程序計數(shù)器)寄存器:
    每個jvm線程有自己的pc寄存器,在任何點,每個jvm線程執(zhí)行一個單個方法的 代碼,這個方法被稱為那個線程的當前方法。如果方法是native,則pc寄存器的值沒有定義,如果不是,則pc寄存器中存放當前正在執(zhí)行的jvm指令的地址。
    pc寄存器占一個字寬。

    棧:
    每個jvm線程都有私有的棧。等價于傳統(tǒng)語言的棧,它持有局部變量和部分結果。并參與部分方法的調用和返回。(由于java框架是可以堆分配的,所以java的棧的存儲空間可以是不連續(xù)的)
    java棧可以是固定大小或者是動態(tài)的。jvm實現(xiàn)可以向程序員提供對java棧的初始大小以及動態(tài)情況下的最大和最小值的控制。

    如果固定大小而且線程需要的棧大于棧的大小,則出現(xiàn)stackoverflowError
    如果動態(tài)大小但存儲器沒有足夠空間,則出現(xiàn)outOfMemoryError

    Sun的jdk1.0.2版jvm實現(xiàn)中,java棧是不連續(xù)、動態(tài)的,不收縮,在線程消亡時被回收。java棧的大小的限制可以在jvm啟動時用“-oss”標志設置。

    堆:
    java有一個所有線程共享的堆。堆是用于分配所有類實例和數(shù)組的運行期數(shù)據(jù)區(qū)。
    堆在jvm啟動時創(chuàng)建,由garbage collector回收。
    堆可以是固定的,也可以動態(tài)擴展,并且支持自動收縮,存儲器無需連續(xù)。
    jvm實現(xiàn)可以向程序員提供堆初始大小以及動態(tài)情況下的最大和最小值的控制。

    如果要求的堆比系統(tǒng)能夠擁有的堆大,則出現(xiàn)OutOfMemoryError

    Sun的jdk1.0.2中,堆是動態(tài)的,從不收縮它的堆,它的初始值和最大值在啟動時用“-ms”和“-mx”指定。

    方法區(qū):
    方法區(qū)類似于傳統(tǒng)語言中編譯后代碼的存儲區(qū),存儲每個類結構例如:常數(shù)池、域、方法數(shù)據(jù)。
    方法區(qū)是虛擬機建立的時候啟動的,邏輯上是垃圾回收實現(xiàn)的一部分,但可以不實現(xiàn)。
    方法區(qū)可以固定大小,可以動態(tài),可以收縮,無需連續(xù)存儲器。
    jvm實現(xiàn)可以向程序員提供方法區(qū)初始大小以及動態(tài)情況下的最大和最小值的控制。
    outofmemory異常

    sun的jdk1.0.2中,仿佛去是動態(tài)的,不收縮的,不提供程序員對其最大最小值的控制。

    常數(shù)池:
    常數(shù)池是每個類或接口的constant_pool的運行期表示。功能類似于傳統(tǒng)語言的符號表,但含更寬的數(shù)據(jù)范圍。(詳細見第五章)

    自身方法棧(估計應該是native method stack)
    其管理和普通棧類似,每個線程一個,線程創(chuàng)建時創(chuàng)建,只是使用非java的native語言(如C)寫成,以支持native方法。

    Sun的jdk1.0.2版jvm實現(xiàn)中,java棧是固定大小。java棧的大小的限制可以在jvm啟動時用“-oss”標志設置。

    3.6框架
    jvm frame用于存儲數(shù)據(jù)和部分結果,以及動態(tài)鏈接,返回方法的值,和調度異常。

    每次java方法調用時創(chuàng)建一個新的框架,當方法結束的時候,框架撤銷。框架從創(chuàng)建它的線程的棧里分配,每個框架有自己的局部變量集和操作數(shù)棧(這些可以一次分配,因為都是編譯期可知的)。
    對于一個給定線程的任何點,只有一個活躍框架,稱為當前框架,局部變量和操作數(shù)棧上的操作總是引用當前框架。

    局部變量:
    每個jvm frame包含一組局部變量,局部變量總是一個字寬,long型,double型存為兩個局部變量。

    操作數(shù)棧:
    每個jvm frame包含一個操作數(shù)棧,絕大多數(shù)java操作從當前操作數(shù)棧取值。

    動態(tài)連接:
    jvm frame通過包含一個對當前類的常數(shù)池的引用來達到動態(tài)鏈接的目的,java 的class文件仍然可以使用符號引用訪問變量或方法。


    java中的i=i++從這一章來理解應該是和框架(jvm frame)這個概念有關,也就是++操作符被實現(xiàn)成為了一個方法,而不是一個虛擬機指令,這樣就可以解釋了,但是目前還沒有看到有++操作符應該被實現(xiàn)為一個方法的說明,另外java的方法調用是值傳參的,這種情況應該也不會出現(xiàn)值回寫的情況.
    看至3。6結束。

    3.7對象的表示
    jvm不對對象表示要求任何特殊的內(nèi)部結構。
    在sun公司的jdk實現(xiàn)中,對象實例就是指向一個句柄的指針,而這個句柄本身又包括兩個指針:1、一個指向包含該對象方法而代表該對象類型的class對象的指針,2、另一個指向在java堆中為該對象實例分配的存儲區(qū)域。
    別的jvm實現(xiàn)可以采用諸如:直接插入高速緩存技術,等。

    3.8特殊的初始化方法
    實例初始化:構造函數(shù)作為具有特殊名字《init》的實例初始化方法出現(xiàn),方法的名字由編譯器提供,這個方法由jvm在內(nèi)部由invokespecial指令調用,只能使用于未初始化的實例上,不能被java程序員使用。
    類和接口的初始化:類和接口的初始化具有特殊的名字《cinit》,方法的名稱由編譯器提供,該方法由jvm顯示調用,從不直接被java代碼和jvm指令調用,只是作為類初始化進程的一部分被間接的調用。

    3.9異常
    異常一層層向上拋,丟棄當前層的操作數(shù)棧和局部變量,知道遇到catch為止,如果到頂層還沒有catch,當前線程將被結束。

    3.10class文件格式
    class文件是平臺無關格式的二進制文件,class文件格式精確定義了文件的內(nèi)容。

    3.11指令集概述
    一個jvm指令由一個字節(jié)的操作碼后跟0個或多個操作數(shù)構成。操作數(shù)的數(shù)目由操作碼決定。
    當操作數(shù)多于一個字節(jié)的時候,以高位字節(jié)在前的方式存儲。
    字節(jié)碼指令流只是單字節(jié)對齊的(除了tableswitch,和lookupswitch的特殊指令對操作數(shù)的特殊要求),放棄了數(shù)據(jù)對齊,反映了對數(shù)據(jù)緊湊性的偏好,而排除了可能提高jvm仿真器性能的某些實現(xiàn)技術。
    jvm指令中絕大多數(shù)是類型相關的,也就是作用于特定類型的操作數(shù)的。并在該指令的助記符中顯示的標識出來。
    具體的指令集后面細說。

    3.12公共設計、私有實現(xiàn)
    公共概念:class文件格式和jvm指令集

    posted @ 2006-08-24 17:01 flyffa 閱讀(1228) | 評論 (0)編輯 收藏

    2004-09-27

    學習java虛擬機規(guī)范之前,已經(jīng)有了心理的準備,像我這種從應用中開始真正了解計算機的人,可能會遇到許許多多的問題,很多關于底層的,硬件級別的概念可能會無法理解,但是只要能開始,就是進步,不是嗎。

    第一章:前言

    ************************************************************************************************

    java虛擬機假定任何實現(xiàn)技術或主機平臺,它并不非得是解釋型的,它也可以像傳統(tǒng)的程序設計語言一樣,通過把它的指令集編譯成一個實際的CPU指令集來實現(xiàn)。它也可以直接用微代碼或者直接用芯片來實現(xiàn)。

    ?

    第二章:Java概念
    (這個部分是對Java語言的介紹,這里羅列出一些比較細節(jié)的概念)
    1、Java語言使用Unicode1.1.5版編寫。
    2、除了注釋、字符、字符串、標識符之外,Java程序的所有輸入元素都是ascii碼形式。
    ?? 測試證明變量定義可以使用中文。
    3、字符串文字以及更一般的常數(shù)表達式的值的字符串,被用方法String.inter內(nèi)部化以共享惟一的實例。
    4、整型和引用類型可以轉化為boolean型,非零和非null都為true。(以標準C++的方式x!=0和obj!=null)
    5、三種引用類型:類引用,接口引用,數(shù)組引用,所有對象包括數(shù)組都支持Object類的方法。
    6、執(zhí)行順序:裝載類---鏈接一個類型或者類(檢驗,準備和可選的解析)---初始化(這個初始化可能引起相關父類的初始化動作)
    7、類實例退出的時候自動的調用finalize()方法
    8、類卸載的時候自動調用classFinalize()方法。
    9、虛擬機退出的條件:1、所有非守護線程中止。2、顯式調用了Runtime或者System的exit方法

    ************************************************************************************************
    6、變量是一種存儲位置,有相應的類型,稱為編譯期類型,可以是引用類型,也可以是基本類型。
    ?? 問題:變量本身是怎樣的一個存在,它的結構如何。
    7、java語言中多次提到基本數(shù)值類型的特殊值NaN,但是不知道其表現(xiàn)和使用。


    2004-6-3凌晨1點,讀至2、16 執(zhí)行,31頁。
    2004-6-3下午五點:讀至34頁
    2004-6-6晚上8:30-10:30,讀至第三章:java虛擬機結構:41頁

    為了了解i=i++的奧秘,我提前閱讀了第八章:線程和鎖,好像能夠理解,結果又被全盤推翻了。(通查網(wǎng)上的說法:i=i++的特殊之處在于i++,或者說是++操作符的實現(xiàn),i++操作的方式是1:將i值拷貝一份到另一內(nèi)存區(qū)域,2、對原i值執(zhí)行++操作,3、將i++的結果放入新分配的區(qū)域內(nèi),而對于i=i++,就多了第四步:4、將i++值回寫到i的存儲區(qū)域中),但java為什么這么實現(xiàn)不是很清楚

    posted @ 2006-08-24 16:59 flyffa 閱讀(979) | 評論 (0)編輯 收藏

    20060607
    1.2版本,下載地址
    http://www.tkk7.com/Files/flyffa/javaSms1.2.rar
    1、對聯(lián)通手機號碼進行支持,主要的處理就是在短信中心的控制上
    2、對容錯能力進行提高,對于發(fā)送失敗的信息,加以提示.
    3、解決以手機做為gsm模塊時不能正常接收短信的問題,從而達到聊天的效果。

    如果需要了解其他更多,訪問:
    http://www.tkk7.com/flyffa/archive/2006/05/15/46177.html
    posted @ 2006-06-07 13:11 flyffa 閱讀(565) | 評論 (1)編輯 收藏

    僅列出標題
    共3頁: 上一頁 1 2 3 下一頁 
    主站蜘蛛池模板: 久久精品国产亚洲AV天海翼| 亚洲国产精品SSS在线观看AV| 成人免费视频一区| 日韩版码免费福利视频| 国产精品久久久久久久久免费| 99久久99热精品免费观看国产| 三年片在线观看免费观看大全动漫 | 久草视频免费在线| ww4545四虎永久免费地址| 1000部啪啪未满十八勿入免费| 亚洲成年人免费网站| 亚洲综合免费视频| 性做久久久久久久免费看| 午夜爱爱免费视频| 日本免费一区二区三区最新| 免费v片视频在线观看视频| 亚洲阿v天堂在线2017免费| 亚洲无线一二三四区手机| 日韩亚洲欧洲在线com91tv| 亚洲视频一区调教| 亚洲明星合成图综合区在线| 亚洲天堂男人影院| 亚洲aⅴ无码专区在线观看| 男男gay做爽爽的视频免费| 一级毛片在播放免费| 国产成人精品一区二区三区免费| 99久久国产免费-99久久国产免费 99久久国产免费中文无字幕 | 国产aⅴ无码专区亚洲av麻豆| 亚洲熟妇丰满多毛XXXX| 久久夜色精品国产噜噜亚洲AV| 亚洲第一永久在线观看| 亚洲欧美国产日韩av野草社区| 黄网站色视频免费观看45分钟| 三年片免费观看大全国语| 91高清免费国产自产拍2021| 国产成人免费爽爽爽视频| 免费中文字幕一级毛片| 亚洲va久久久噜噜噜久久天堂| 亚洲a视频在线观看| 白白色免费在线视频| 国产免费拔擦拔擦8X高清在线人|