




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
摩根面试准备要点JVM架构(Vincent)
主要包括两个子系统和两个组件:Classloader(类装载器)子系统,Executionengine(执行引擎)子系统;Runtimedataarea(运行时数据区域)组件,Nativeinterface(本地接口)组件。Classloader子系统的作用:根据给定的全限定名类名(如java.lang.Object)来装载class文件的内容到Runtimedataarea中的methodarea(方法区域)。Javsa程序员可以extendsjava.lang.ClassLoader类来写自己的Classloader。Executionengine子系统的作用:执行classes中的指令。任何JVMspecification实现(JDK)的核心是Executionengine,换句话说:Sun的JDK和IBM的JDK好坏主要取决于他们各自实现的Execution
engine的好坏。每个运行中的线程都有一个Executionengine的实例。Nativeinterface组件:与nativelibraries交互,是其它编程语言交互的接口。
Runtimedataarea组件:这个组件就是JVM中的内存。下面对这个部分进行详细介绍。Runtimedataarea的整体架构图Runtimedataarea主要包括五个部分:Heap(堆),MethodArea(方法区域),JavaStack(java的栈),ProgramCounter(程序计数器),Nativemethodstack(本地方法栈)。Heap和MethodArea是被所有线程的共享使用的;而Javastack,Programcounter和Nativemethodstack是以线程为粒度的,每个线程独自拥有。HeapJava程序在运行时创建的所有类实或数组都放在同一个堆中。而一个Java虚拟实例中只存在一个堆空间,因此所有线程都将共享这个堆。每一个java程序独占一个JVM实例,因而每个java程序都有它自己的堆空间,它们不会彼此干扰。但是同一java程序的多个线程都共享着同一个堆空间,就得考虑多线程访问对象(堆数据)的同步问题。(这里可能出现的异常java.lang.OutOfMemoryError:Javaheapspace)Methodarea在Java虚拟机中,被装载的class的信息存储在Methodarea的内存中。当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件内容并把它传输到虚拟机中。紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区。该类型中的类(静态)变量同样也存储在方法区中。与Heap一样,methodarea是多线程共享的,因此要考虑多线程访问的同步问题。比如,假设同时两个线程都企图访问一个名为Lava的类,而这个类还没有内装载入虚拟机,那么,这时应该只有一个线程去装载它,而另一个线程则只能等待。(这里可能出现的异常java.lang.OutOfMemoryError:PermGenfull)Javastack
Javastack以帧为单位保存线程的运行状态。虚拟机只会直接对Javastack执行两种操作:以帧为单位的压栈或出栈。每当线程调用一个方法的时候,就对当前状态作为一个帧保存到javastack中(压栈);当一个方法调用返回时,从javastack弹出一个帧(出栈)。栈的大小是有一定的限制,这个可能出现StackOverFlow问题。下面的程序可以说明这个问题。publicclassTestStackOverFlow{publicstaticvoidmain(String[]args){Recursiver=newRecursive();r.doit(10000);//Exceptioninthrea}}袜cl桶as沾s脸Re调cu垂rs尾iv逢e括{愉蚊pu匠bl谷ic围i民nt梁d止oi掏t(强in眼t觉t)虑{耻锦杨if扎(顿t录<=霉1占)捧{父守液屯re览tu冲rn紧1钟;塌断梅}唉董答re骗tu教rn壁t项+瑞d屈oi归t(琴t群-纠1)命;}}倒喝Pr挨og痕ra坐m战co羽un远te蹈r躺饱每个巩运行蔽中的钟Ja酱va旨程序种,每嫂一个驶线程吐都有片它自俊己的蒙PC耻寄存拖器,飘也是萍该线芹程启豆动时使创建所的。告PC谁寄存波器的近内容圆总是管指向蓄下一盖条将替被执驾行指营令的蹄地址他;,抱这里蜻的地剂址可郊以是头一个量本地阶指针矮,也秒可以当是在皱方法辞区中沾相对须应于顾该方巾法起极始指狸令的粱偏移稼量。计敏Na今ti纹ve筹m嚼et潮ho菜d馆st锹ac沈k陷朋对于坐一个只运行暮中的镇Ja算va蓝程序轨而言茅,它帮还能薄会用犁到一盘些跟岁本地哭方法粮相关孩的数尝据区著。当袋某个牧线程岸调用呼一个泊本地惰方法昌时,势它就僵进入辣了一浇个全押新的面并且鹊不再昌受虚日拟机个限制郑的世曲界。虾本地蜡方法到可以肠通过拘本地宗方法场接口辞来访谁问虚远拟机稻的运滩行时扭数据乌区,周不止吊与此巨,它肃还可状以做峡任何劝它想挂做的缓事情戒。比注如,涌可以肆调用外寄存党器,狐或在忠操作统系统跑中分期配内闻存等且。总感之,净本地椅方法脊具有酱和J源VM暑相同旨的能朵力和码权限字。朵(绞这里栋出现梁JV饲M无捉法控妇制的颗内存亏溢出士问题抄na冤ti写ve方h叉ea椅p厘Ou斧tO厌fM吨em性or志y飘)液CL蚊as挑sL睁oa跪de绒r然(俊Vi励nc畏en抖t)晶Ja草va忽的可添执行劝文件捎不同券于C伤/C叠++票,J粥av饱a编掀译器谁只产善生中籍间字局节码偏文件膊(.骄cl溪as叙s文唱件)际,由似Ja叮va花虚拟体机(焦ja商va瓜.e斤xe燕)解壮释执均行。纱Ja禾va必发布省的程零序(教JA抄R包元)也不多半蹲是一检堆c迈la爽ss祝文件成,运笋行时渴由C样la朵ss淘Lo己ad颈er虽加载瑞到J浊av城a虚叨拟机货中执馒行。欲Cl窜as丘sL腔oa知de佩r是夺Ja榨va架虚拟奖机的凑主要料组成音部分临,由椅Ja子va秩语言课编写奇,用那户可调以实傍现自愁定义办的C三la样ss教Lo声ad木er不来完肤成特房定的献功能语。下俩面我葬们用铜例子密说明制Cl腾as范sL灶oa浩de削r。杠胀JV呼M规苹范定唱义了估两种摧类型居的C马la润ss摊Lo烫ad羡er享:B阳oo壶ts选tr陡ap虽C仙la锅ss惭Lo演ad扩er玩和U亮se拢r-菌de剃fi巴ne是d没Cl押as蜂sL断oa突de好r。振来JV退M在约运行页时会告产生根三个何Cl仿as绿sL改oa旋de善r:币Bo哲ot告st偏ra精p自Cl缩as正sL撒oa搞de菊r、课Ex镇te冷ns赠io善n府Cl及as匠sL狡oa不de猜r和矿Ap援pC众la俯ss苗Lo辉ad瑞er摸。特Bo英ot陆st叠ra坛p是遥用C互++微编写陡的,穿我们旦在J急av概a中桂看不者到它凭,是祸nu样ll彼,是永JV己M自侄带的恋类装仆载器商,用针来装面载核沃心类牺库,钞如j啄av专a.莲la鹅ng持.*义等。币Ap移pC碑la果ss滴Lo泽ad念er堤的P除ar琴en懒t是锈Ex孔tC落la礼ss升Lo傅ad练er容,而氏Ex垄tC态la射ss旧Lo旷ad薯er局的P旗ar纺en狼t为状Bo隔ot兔st舍ra竹p想Cl般as异sL宣oa验de隶r。辩接ja提va度中,挪什么授叫不会可更嫂改的棍类(障im窑mu效ta高bl增e馒cl蔽as买s)秒(K恨ev泊in捞T骨am夸)炊从字扩面意薪思来暖理解帖就是泰不会浑发生价变化能的类余,那岔么是延什么鄙不会后发生膊变化弹呢,驰其实存就是衫类的潮状态汁,也充就是晋不变宋类的呢实例虫一旦辽被创野建,凭其状漂态就烛不会印发生篮变化辰,举肌个例剥子:规如果哲人是必一个残cl抛as没s,波那么是我们级中的句每一达个都便是人旬这个巩类的群具体送的i皱ns但ta究nc都e,最如果沈人这某个类削只有屯一个屠状态荐就是四生身率父母冒,那秃么它勺就是窄一个兰不变错类,出因为宽每一乌个人芳在出庙生的逮那一货刹那莫,生剩身父债母就劣已经砖被设猾置了木值,肥而且赶终生杏都不男会发湿生变搁化。收糊不变跪类有浓什么忘好处忆呢?坦1)钟椅不变祝类是企线程找安全你的,采由于馋不变牌类的败状态万在创断建以结后不刮再发蹄生变仓化,呜所以米它可劳以在腥线程摘之间庸共享翼,而贪不需轻要同情步。弦2)锤棒不变砖类的川in否st每an错ce接可以月被r董eu相se葛创建本类的忠实例控需要彻耗费等CP锋U的学时间层,当微这个钞实例旱不再右被引形用时旨,将头会被蒸垃圾侧回收恳掉,非这时假候,窜又需颤要耗嫩费C绳PU冲的时陷间。凳对于自不变眨类而洞言,绿一个众好处抗就是昂可以舍将常龙用的嫌实例激进行店缓存友,从锯而减两少了傲对象口的创览建。备举个响例子块,对床于布陡尔型再,最第常用全的便耗是t灰ru草e驻an顾d男fa形ls慌e。译JD济K中眼的B种oo崭le耍an萌类就郊是一采个不泽变类很,并肥且对亭这两沙个实篮例进挤行了货缓冲国。嘉pu蒸bl夸ic惭f旨in旅al冻c魄la吃ss回B麦oo慰le今an铁i斜mp理le伤me夜nt艇s末ja距va坝.i锐o.这Se边ri帅al虑iz醉ab嚼le码{档/*轧*塑骂逢*阻T撑he吐<败co谨de霉>B难oo世le导an爱</槐co周de资>烫ob丘je朴ct针c誉or扔re隶sp洗on摊di放ng解t糠o森th散e做pr虏im征it幻iv赚e巾段邻*换v鼓al享ue快<惊co环de辨>t位ru曾e<上/c坡od森e>范.*/跪pu垦bl注ic质s然ta田ti喂c省fi捎na肌l察Bo溪ol险ea茶n渗TR般UE蛾=禽n化ew间B问oo奏le予an访(t经ru钉e)裁;舒/陪**福指抛铅*状T绑he贸<棍co认de姐>B勒oo纪le艺an副</沫co境de种>族ob灵je素ct具c贫or川re德sp爪on鸭di慈ng渡t泛o阶th丹e名pr成im雷it衰iv质e懒斗镰*堡va丝lu随e督<c陪od杯e>涂fa常ls侵e<亩/c特od屠e>吴.静决会*壶/刊pu造bl捎ic挥s舌ta专ti世c何fi暂na更l王Bo影ol监ea师n统FA渐LS贯E拥=述ne抵w追Bo贞ol臭ea炭n(豪fa裙ls漆e)融;说//柜这么个方岂法不络会创罪建新敞的对绢象,摘而是妙重用盼已经纵创建姐好的永in糕st炮an猪ce巾拒pu明bl赏ic搂s旧ta夕ti摘c炭Bo基ol摔ea慎n烟va鱼lu豪eO贺f(厅bo栋ol缘ea钉n侄b)拆{角找畅收场re贿tu掘rn认(训b严?味TR苍UE床:教F溉AL们SE绍);}}雷3)置设不变块类的忽某些捕方法家可以牛缓存庄计算弦的结俊果露ha扇sh要Co相de诵这个稍方法将来自亿于O税bj定ec们t这辨个类宰,这纸个方捞法用凉来返后回对态象的即ha父sh膜Co跟de俱,主扯要用自于将渴对象师放置似到h得as丝ht跳ab晓le乐中时祸,来信确定奸这个访对象估的存剩储位免置。唱对于慌一个猎不变混类的骨实例斩,它叼的h要as垫hC帝od搂e也额是不贝变的遮,所忧以就俘可以概缓存浴这个笨计算典的结号果,却来提疏高性宪能,价避免恐不必择要的渗运算援,J门DK仿中的漏St青ri枝ng膨类就均是一质个例咳子。摸pu场bl犹ic关f吹in担al应c遗la流ss瓜S春tr溉in洽g{榆进京跟/霉**窑C啄ac沙he茂t烛he银h妨as栏h胖co对de仔f守or胶t除he他s面tr薄in诸g缝*/日pr叠iv败at史e愧in魂t饥ha墨sh完;傍//喷D治ef镰au没lt窗t狮o别0饶赠朵疮p贵ub德li螺c脏in叨t轮ha饿sh箩Co停de挡()剩{异in卖t崖h恶=拒ha必sh枯;践if租(妻h企==萌0拐)理{万悟祸价/倒/熔co钟mp橡ut扑e磁th屡e雨va观lu秒e焰显工砍豆闹绸ha秘sh菌=阳h椅;龄//猎c店ac样he缴t式he即v担al挪ue别陷页骑重}讲教瞎询殊re肌tu潮rn骆h缝;忽亏杠}}捡在J线DK减中,姓S按tr疼in怕g,谦t放he洒p刷ri口mi盯ti罗ve状w绑ra陕pp扎er东c碑la般ss关es接,狮an馋d弃Bi伐gI丢nt辅eg叹er宇a荒nd苍B烤ig绒De苹ci维ma炊l都支是不罗变类丹。并如果堪一个堡类是扁不变捧类,鹊这个陷类是伯不是项就不览能有锤改变侄状态标的方云法呢五?要答案割当然粘是否聋定的积,S那tr符in限g是幅一个倘不变往类,货仍然炸有r草ep垫la些ce克,r归ep恶la瞧ce淋Al因l这盏样的闪方法慌,而付St客ri涛ng倡仍然裕是一晓个不铃变类利,那葛是因郊为在渴这些姿改变粘状态塘的方据法中涨,每尤次都坑是新河创建孙一个为St买ri邀ng士对象泛。据如果脱大家岩理解夹了不畏变类软,那辣也就讽不难仁理解糕为什劳么在置做S串tr趟in服g的兆co狭nc葛at它en谈at弟e时右,应愉当用丛St赤ri边ng驻Bu肯ff祥er事而不似是用戒+的沉操作滨符。用如何掀正确微使用境St版ri副ng窝呢?守1)滑丘不要分用n贞ew猪去创落建S灿tr伐in怪g对女象。肤如果民使用馆ne归w去病创建只St宜ri冒ng迟,那米么每磨次都注会创浩建一饶个新草对象盐。冻pu辈bl聪ic资s伯ta鼠ti乌c驳vo她id缩m您ai温n(膜St良ri峡ng俯[]酬a减rg薄s)拾{娃甲联腐绣St违ri速ng象A变1沈=忙"A负";饭切达述堆St秃ri坏ng渴A寨2过=嚼"A腊";炸届//臂I缴t中wo基n'奥t桃cr乓ea叨te捞a额n国ew灭o救bj奔ec冤t程济湖女忽ch挠ec在kI滑ns积ta槽nc敬e(司A1吗,惑A虑2)渠;忠/眠/乖Re逗su刑lt眯:所T展he塞y筐ar旺e膛sa洒me狐i疲ns尺ta瓣nc笑es建摘渣桶葛St职ri床ng愁B殃1钩=奏ne饰w磨St只ri鼠ng躬("移A"束);惜/拦/酸cr符ea甘te艺a茶n旁ew勿o骑bj翅ec宫t咏哈眯灭拆St饥ri挎ng气B鸡2娃=脉ne动w迫St戏ri荡ng军("驶A"做);埋/究/笼cr屋ea钳t蠢a壶ne痰w谦ob愧je毁ct浑缘守扩证ch侵ec捎kI渠ns废ta絮nc召e(忠B1拘,壶B2闸);骨/猾/营Re中su揪lt想:饥T位he洗y冷ar徐e死di枣ff塞er钟en切t初in乔st论an祸ce酬s灰络径}奔pr乔iv苦at浆e喜st件at付ic灯v闭oi晶d碌ch庄ec面kI歇ns悟ta及nc什e(陡St辰ri或ng期a搅1,条S筹tr激in贝g词a2熟)伍{另挂顿贩守if墓(染a1煌=违=响a2统)治{跑昨师枣谎散罗Sy驾st母em娇.o轰ut近.p列ri跪nt醒ln霉("款Th狠ey咐a肺re武s残am闲e研in丰st逃an丑ce左s"丧);牙加裤唯参}真el务se掏{民忆号葬汪脂祥Sy锈st抽em继.o惨ut辛.p蛇ri璃nt遵ln锯("困Th务ey凤a激re骆d骡if拴fe劈re买nt不i匹ns勒ta分nc旬es悼")涂;名饼咬强蓬}刻姐胞}遮2)兽祝应当茅用S露tr皱in傅gB摔uf阶fe煤r来棍做连捆接操析作学因为末St捧ri技ng败是一胖个不数变类同,那顿么在蠢做连法接操含作时者,就拴会创获建临乐时对标象来亦保存驴中间济的运括算结沙果,爆而S缘tr痰in托gB辜uf毅fe略r是例一个狭mu举ta凭bl布e桥cl栽as灰s,虚这样渣就不胁需要像创建陕临时粒的对闹象来夫保存来结果摸,从可而提滨高了惭性能炉。浮JA卡VA虏G懒ar南ba沫ge朵C态ol猛le完ct端io仆n比(居Vi羽nc朵en作t)购垃圾积分代燥回收殃算法剩(G宋en诞er庭at辈io费na液l迟Co刃ll晃ec拜ti状ng叉)藏基于得对对些象生梦命周泉期分合析后唯得出觉的垃萄圾回浇收算墙法。款把对吵象分痕为年籍青代轰、年摸老代争、持限久代幼,对既不同晨生命委周期挽的对提象使驶用不软同的公算法滤(上灯述方粒式中倡的一辅个)跃进行酱回收公。现燃在的僻垃圾觉回收仁器(必从J已2S蚀E1宾.2壤开始泛)都扭是使滤用此掌算法她的。买刺如上永图所膨示,脖为J蜂av揭a堆茄中的悄各代仇分布进。储1.贺Y巡ou寻ng障(年六轻代是)恋JV紫M诵sp计ec哀if洲ic句at言io框n中至的璃He妹ap冒的一怠部份碑柄年轻狐代分端三个类区。密一个衣Ed首en割区,炮两个乡Su尺rv热iv约or穷区。匆大部幅分对殿象在犁Ed票en查区中家生成烫。当轿Ed言en准区满凑时,嫌还存河活的氧对象槐将被继复制务到S棉ur专vi缓vo陆r区耀(两筐个中趁的一伞个)白,当荒这个纪Su涛rv赏iv旬or阔区满并时,赢此区惧的存搁活对它象将损被复雨制到遥另外妖一个梦Su裹rv枕iv音or叔区,俱当这究个S庸ur剥vi瑞vo悼r去止也满胃了的另时候险,从球第一御个S犹ur蛛vi费vo篇r区沉复制进过来赠的并针且此每时还五存活滚的对紧象,软将被横复制派年老尺区(拌Te胁nu既re牲d)速;。挡需要腾注意才,S合ur漏vi士vo吸r的号两个政区是尸对称涉的,侍没先药后关美系,路所以撞同一狸个区只中可骂能同尊时存记在从敞Ed狡en补复制慎过来牺对摸象,煌和从圣前一遭个S主ur纪vi丹vo饮r复遇制过桑来的保对象轿,而例复制勒到年锁老区罗的只丹有从浑第一阳个S鬼ur靠vi帽vo终r去旬过来呆的对看象。祸而且宪,S榆ur来vi捕vo泉r区绵总有驴一个菌是空暴的。指选2.孩T编en愚ur学ed披(年驳老代寺)跨JV损M丽sp版ec醒if互ic叶at喇io袍n中蝇的客He搏ap绘的一泳部份消订年老赚代存萌放从地年轻蹈代存倘活的竖对象撑。一算般来交说年析老代由存放值的都攀是生合命期锯较长妻的对沙象。痕浴3.尖P剩er残m(姨持久败代)贺寺JV极M但sp值ec而if棒ic逝at众io谣n中仇的译Me娱th柴od摆a剃re第a乏用于慨存放首静态剂文件座,如榨今J滤av问a类伤、方螺法等雨。持鞠久代番对垃源圾回熟收没辫有显蛙著影株响,显但是干有些请应用醒可能习动态楼生成虽或者告调用嘉一些扔cl巧as胜s,卵例如北Hi效be膝rn患at织e等窃,在自这种毕时候顾需要杨设置蜡一个夏比较年大的瓶持久忆代空屈间来谜存放司这些岭运行闯过程龄中新馒增的伞类。捷持久弹代大狂小通可过-给XX惹:M狡ax而Pe它rm寇Si至ze穗=进什行设吨置。引采用宇分区阴管理表机制够的J悬VM赖将J祝VM崭所管标理的赌所有如内存缘资源此分为响2个蒸大的誉部分测。永箱久存霞储区堪(P观er终ma像ne椅nt请S迅pa筐ce粪)和竖堆空被间(由Th麦e沃He尘ap困S肃pa让ce阵)。穗其中袭堆空视间又罗分为妈新生沿区(抹Yo由un凉g房(N烤ew党)今ge挎ne垫ra杂ti好on玻s候pa刷ce舞)和菠养老泰区(膝Te平nu烫re坏(亭Ol腐d)植g源en胖er侵at恭io卷n驶sp漂ac炊e)输,新胖生区寿又分配为伊像甸园迫(E喷de扁n势sp补ac盒e)坟,幸锹存者吊0区疑(S氧ur欺vi鱼vo厌r昌0搭sp可ac榨e)差和幸屑存者炮1区晴(S括ur光vi和vo庸r爷1饰sp扬ac桥e)费。具瓦体分辆区如只下图桶:顶那J富VM够他的机这些片分区圆各有纹什么营用途醋,请粉看下鞋面的死解说哨。若永久总存储胡区(队Pe连rm完an薄en龙t母Sp肤ac文e)屈:永款久存馋储区丽是J窝VM锯的驻秃留内欲存,首用于廊存放探JD启K自送身所赞携带绿的C篇la泉ss雷,I给nt炸er居fa伐ce旗的元均数据岩,应孤用服驼务器沉允许限必须敌的C组la亿ss匠,I告nt它er铸fa栽ce策的元骆数据饶和J争av供a程诉序运津行时既需要腰的C罪la种ss炸和I做nt桐er须fa共ce疤的元劲数据烂。被赶装载店进此丹区域炊的数底据是组不会册被垃鲁圾回狂收器丽回收灯掉的法,关览闭J灾VM描时,叫释放侄此区据域所欠控制猎的内著存。叙称堆空治间(善Th尊e售He养ap帮S常pa围ce抽):家是J换AV外A对员象生源死存精亡的戏地区把,J闪AV霞A对仅象的伪出生陆,成蛇长,势死亡吩都在呈这个乡区域戒完成使。堆富空间糊又分它别按谁JA阅VA蔬对象枕的创党建和浸年龄奸特征稍分为责养老闸区和钥新生发区。晴窃新生蜻区(穴Yo框un以g遥(N救ew量)负ge体ne帖ra杀ti驾on迫s斜pa足ce刃):粉新生锐区的斯作用和包括凉JA杂VA与对象迹的创你建和孕从J遗AV棒A对折象中隶筛选袜出能路进入窑养老爹区的膛JA余VA芹对象习。烦伊甸清园(畏Ed纳en傅s暴pa蒜ce蒙):搜JA蠢VA原对空浊间中禽的所丢有对覆象在说此出伞生,像该区使的名毯字因旦此而恰得名挎。也龟即是咬说当轧你的拔JA木VA快程序吗运行衔时,慨需要陡创建临新的箭对象趁,J歌VM稀将在以该区质为你披创建刺一个涂指定连的对文象供盛程序修使用缴。创粱建对爪象的联依据职即是讨永久董存储钩区中造的元狭数据变。扣幸存跪者0直区(灯Su羽rv孤iv歼or羞0村s拖pa成ce新)和破幸存趟者1热区(蚁Su速rv匪iv岁or蔬1读sp唉ac飘e)涛:当抚伊甸适园的都空间箱用完哪时,椒程序暂又需包要创窄建对勉象;隆此时座JV搞M的蔑垃圾静回收赔器将安对伊敏甸园阻区进荐行垃桨圾回召收,洲将伊肯甸园递区中辱的不骆再被疗其他崭对象杂所引慎用的罪对象饶进行守销毁主工作出。同劳时将参伊甸岩园中浓的还插有其援他对乞象引朽用的诊对象芹移动甘到幸岁存者隔0区蒸。幸老存者捞0区炭就是牵用于割存放纹伊甸啊园垃黑圾回忽收时疏所幸拖存下给来的睬JA谊VA症对象计。当楼将伊锻甸园巧中的逮还有扇其他驴对象汪引用雁的对蔑象移冒动到孤幸存毕者0竹区时化,如珍果幸键存者富0区桐也没遍有空宣间来旗存放欣这些边对象全时,碰JV意M的兽垃圾烘回收幸器将接对幸吨存者驼0区妥进行荒垃圾含回收叙处理瓦,将据幸存指者0德区中记不在询有其谣他对瞒象引蚁用的削JA聋VA存对象重进行兼销毁困,将刑幸存汇者0辟区中胜还有有其他练对象冬引用拴的对尼象移状动到店幸存远者1颈区。姓幸存塞者1敌区的鼓作用争就是裹用于剃存放丘幸存堂者0趣区垃挖圾回拴收处狡理所扁幸存役下来纸的J上AV马A对仅象。济挤养老娱区(杰Te罪nu忍re拾(玻Ol统d)联g因en撇er贺at楼io味n侮sp渐ac森e)眼:用朱于保津存从闯新生梦区筛掌选出赵来的惠JA答VA壶对象碗。窄上面投我们体看了兴JV橡M的石内存孕分区僚管理烧,现京在我结们来抬看J点VM银的垃椅圾回俩收工肥作是极怎样何运作丘的。治首先鼻当启洪动J皂2E形E应颤用服铅务器络时,哨JV蹈M随卵之启碑动,搁并将辟JD言K的绒类和羞接口灵,应雄用服巩务器拾运行摧时需弱要的玩类和额接口呢以及洞J2紫EE秀应用府的类驾和接以口定掩义文肯件也搅及编滴译后葱的C誉la钟ss剪文件阵或J结AR慨包中顶的C跃la炮ss黄文件工装载叙到J长VM酱的永集久存证储区赛。在垮伊甸污园中碑创建纵JV杀M,梢应用竟服务销器运考行时政必须纳的J激AV府A对厚象,缝创建棋J2晒EE恒应用矛启动只时必示须创辞建的外JA恰VA徐对象成;J户2E岔E应监用启欣动完慌毕,率可对仍外提旧供服筛务。捷停JV征M在赴伊甸啊园区猴根据伯用户拴的每熔次请蒸求创范建相课应的淡JA免VA汁对象衬,当猛伊甸贺园的板空间习不足针以用雷来创索建新著JA特VA即对象骆的时正候,珠JV往M的伞垃圾青回收示器执运行对衣伊甸签园区卫的垃邻圾回陶收工该作,由销毁成那些摩不再共被其玩他对渗象引昆用的焰JA诸VA熊对象攻(如静果该易对象师仅仅云被一楚个没贿有其店他对崖象引状用的呀对象厕引用恶的话誉,此螺对象粉也被宗归为闪没有汇存在超的必咏要,播依此耍类推械),任并将况那些猛被其寻他对兄象所拍引用热的J锋AV泥A对同象移忘动到休幸存稿者0蚂区。纺闷如果海幸存欣者0攻区有轨足够边控件县存放宗则直救接放拖到幸净存者世0区豪;如离果幸灭存者仙0区侮没有扒足够担空间倦存放板,则曲JV作M的搂垃圾僚回收定器执呼行对索幸存嚷者0晌区的驱垃圾反回收峡工作中,销淹毁那裤些不茧再被挤其他浊对象亡引用植的J透AV路A对故象(勤如果吵该对镰象仅合仅被籍一个吐没有矮其他残对象上引用艘的对轰象引犬用的俩话,羡此对宰象也展被归亚为没支有存牙在的都必要揉,依秃此类拔推)锻,并锐将那右些被更其他采对象测所引垃用的核JA推VA各对象弹移动哭到幸唇存者生1区钢。秩如果历幸存争者1由区有尾足够幅控件靠存放除则直模接放接到幸羡存者巧1区构;如乖果幸君存者匀0区技没有咸足够慨空间甲存放浪,则敌JV旨M的孔垃圾既回收努器执趁行对忍幸存荷者0治区的奖垃圾适回收族工作耍,销享毁那其些不般再被霞其他第对象乒引用上的J面AV授A对沿象(赵如果田该对脑象仅尚仅被臂一个谎没有爷其他刑对象由引用猴的对醉象引乞用的昂话,喝此对世象也女被归镇为没膛有存也在的晃必要甩,依免此类吗推)懂,并衔将那沉些被销其他金对象莫所引嗽用的殿JA缺VA倡对象洪移动蓬到养倘老区势。脖如果角养老监区有亡足够乘控件琴存放毁则直经接放纠到养倒老区组;如垂果养诊老区且没有摧足够布空间阻存放慢,则张JV虚M的瞎垃圾申回收伴器执虏行对羊养老猛区区隔的垃崇圾回朋收工场作,赞销毁材那些玻不再武被其气他对跟象引仪用的福JA冈VA损对象缘(如锻果该赌对象除仅仅伍被一艳个没纵有其堤他对倚象引耀用的淘对象胜引用他的话计,此疼对象堪也被岁归为基没有酷存在料的必构要,商依此忠类推需),肌并保翅留那敲些被铁其他嫂对象炸所引本用的风JA挪VA享对象随。如轿果到疏最后性养老化区,立幸存迫者1米区,某幸存深者0凶区和因伊甸舒园区乖都没蜻有空舅间的沾话,价则J瞎VM咬会报潜告“铃JV疯M堆烟空间熟溢出如(j袍av掘a.霉la正ng淋.O紫ut浸Of聚Me承mo络ry消Er盈ro缘r:盟J过av妨a态he嗓ap起s死pa裂ce紧)”社,也喘即是毙在堆筛空间裕没有汉空间纯来创闭建对传象。侮劈这就腿是J镜VM食的内矩存分晴区管航理,借相比弟不分乘区来毅说;孝一般基情况土下,默垃圾践回收哥的速状度要雅快很能多;屿因为歉在没仔有必竞要的迅时候挑不用蒙扫描秆整片注内存蜜而节叛省了备大量朝时间刺。结通常馋大家屑还会做遇到档另外灰一种娇内存您溢出布错误锣“永旱久存矩储区足溢出栋(j羊av吼a.今la渴ng哲.O熄ut窜Of烂Me袋mo烦ry声Er龙ro疑r:决J松av忠a香Pe戒rm累an旗en栏t优Sp欠ac恋e)出”。所有的垃圾收集算法都面临同一个问题,那就是找出应用程序不可到达的内存块,将其释放,这里面得不可到达主要是指应用程序已经没有内存块的引用了,而在JAVA中,某个对象对应用程序是可到达的是指:这个对象被根(根主要是指类的静态变量,或者活跃在所有线程栈的对象的引用)引用或者对象被另一个可到达的对象引用。ReferenceCounting(引用计数)引用计数是最简单直接的一种方式,这种方式在每一个对象中增加一个引用的计数,这个计数代表当前程序有多少个引用引用了此对象,如果此对象的引用计数变为0,那么此对象就可以作为垃圾收集器的目标对象来收集。优点:简单,直接,不需要暂停整个应用缺点:1.需要编译器的配合,编译器要生成特殊的指令来进行引用计数的操作,比如每次将对象赋值给新的引用,或者者对象的引用超出了作用域等。2.不能处理循环引用的问题跟踪收集器跟踪收集器首先要暂停整个应用程序,然后开始从根对象扫描整个堆,判断扫描的对象是否有对象引用,这里面有三个问题需要搞清楚:1.如果每次扫描整个堆,那么势必让GC的时间变长,从而影响了应用本身的执行。因此在JVM里面采用了分代收集,在新生代收集的时候minor
gc只需要扫描新生代,而不需要扫描老生代。2.JVM采用了分代收集以后,minor
gc只扫描新生代,但是minor
gc怎么判断是否有老生代的对象引用了新生代的对象,JVM采用了卡片标记的策略,卡片标记将老生代分成了一块一块的,划分以后的每一个块就叫做一个卡片,JVM采用卡表维护了每一个块的状态,当JAVA程序运行的时候,如果发现老生代对象引用或者释放了新生代对象的引用,那么就JVM就将卡表的状态设置为脏状态,这样每次minor
gc的时候就会只扫描被标记为脏状态的卡片,而不需要扫描整个堆。具体如下图:3.GC在收集一个对象的时候会判断是否有引用指向对象,在JAVA中的引用主要有四种:Strong
reference,Soft
reference,Weak
reference,Phantom
reference.StrongReference强引用是JAVA中默认采用的一种方式,我们平时创建的引用都属于强引用。如果一个对象没有强引用,那么对象就会被回收。public
void
testStrongReference(){Object
referent
=
new
Object();Object
strongReference
=
referent;referent
=
null;System.gc();assertNotNull(strongReference);}SoftReference软引用的对象在GC的时候不会被回收,只有当内存不够用的时候才会真正的回收,因此软引用适合缓存的场合,这样使得缓存中的对象可以尽量的再内存中待长久一点。PublicvoidtestSoftReference(){Stringstr="test";SoftReference<String>softreference=newSoftReference<String>(str);str=null;System.gc();assertNotNull(softreference.get());}Weakreference弱引用有利于对象更快的被回收,假如一个对象没有强引用只有弱引用,那么在GC后,这个对象肯定会被回收。PublicvoidtestWeakReference(){Stringstr="test";WeakReference<String>weakReference=newWeakReference<String>(str);str=null;System.gc();assertNull(weakReference.get());}PhantomreferenceMark-SweepCollector(标记-清除收集器)标记清除收集器最早由Lisp的发明人于1960年提出,标记清除收集器停止所有的工作,从根扫描每个活跃的对象,然后标记扫描过的对象,标记完成以后,清除那些没有被标记的对象。优点:1解决循环引用的问题2不需要编译器的配合,从而就不执行额外的指令缺点:1.每个活跃的对象都要进行扫描,收集暂停的时间比较长。CopyingCollector(复制收集器)复制收集器将内存分为两块一样大小空间,某一个时刻,只有一个空间处于活跃的状态,当活跃的空间满的时候,GC就会将活跃的对象复制到未使用的空间中去,原来不活跃的空间就变为了活跃的空间。复制收集器具体过程可以参考下图:优点:1只扫描可以到达的对象,不需要扫描所有的对象,从而减少了应用暂停的时间缺点:1.需要额外的空间消耗,某一个时刻,总是有一块内存处于未使用状态2.复制对象需要一定的开销Mark-CompactCollector(标记-整理收集器)标记整理收集器汲取了标记清除和复制收集器的优点,它分两个阶段执行,在第一个阶段,首先扫描所有活跃的对象,并标记所有活跃的对象,第二个阶段首先清除未标记的对象,然后将活跃的的对象复制到堆得底部。标记整理收集器的过程示意图请参考下图:Mark-compact策略极大的减少了内存碎片,并且不需要像Copy
Collector一样需要两倍的空间。JVM的垃圾收集策略GC的执行时要耗费一定的CPU资源和时间的,因此在JDK1.2以后,JVM引入了分代收集的策略,其中对新生代采用"Mark-Compact"策略,而对老生代采用了“Mark-Sweep"的策略。其中新生代的垃圾收集器命名为“minor
gc”,老生代的GC命名为"Full
Gc
或者Major
GC".其中用System.gc()强制执行的是Full
Gc.SpringIOCandAOP(Minjin)IoC和AOP都是Spring的核心思想
当然,最为一个框架级的轻量组件,大量的配置文件是不可缺少的,但是核心是要把这些配置文件,配置节组装起来,并将核心代码编写为完全业务无关的。我们看看Spring是怎么做的。
首先,IoC,控制反转。Spring开发的基本思想:面向接口的编程模式。框架做的越多,应该越能发现接口在其中起到的作用,而Spring将这种想法,开始贯彻到业务的开发中了。Bean的Set方法使用接口作为参数,保证其扩展性,实现依赖关系的松偶尔。所谓的控制反转,作为中文更好理解的一个翻译应该是依赖注入,把依赖的类采用接口的方式,利用Set函数,传入Bean的内部,实现与外界的解耦合。这种注入也可作用于构造函数。
其次,AOP,面向切面的编程方式,我觉得更通俗的说法应该是对容器内的Bean进行方法干涉。被容器中创建的类,看起来执行一个普通的函数调用,因为被容器预处理,而会在方法执行前/后进行一些其他的、可配置的操作。当然,这种方法也同样是面向接口的,或者直接使用反射的。利用java.lang.reflect.InvocationHandler接口可以达到这种干涉的效果。下面是转载的一个简单示例。Java代码import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.lang.reflect.Proxy;
public
class
DynaProxyHello
implements
InvocationHandler
{
private
Object
proxy;
private
Object
delegate;
public
Object
bind(Object
delegate,Object
proxy)
{
xy
=
proxy;
this.delegate
=
delegate;
return
Proxy.newProxyInstance(
this.delegate.getClass().getClassLoader(),
this.delegate
.getClass().getInterfaces(),
this);
public
Object
invoke(Object
proxy,
Method
method,
Object[]
args)
throws
Throwable
{
Object
result
=
null;
try
{
//反射得到操作者的实例
Class
clazz
=
xy.getClass();
//反射得到操作者的Start方法
Method
start
=
clazz.getDeclaredMethod("start",
new
Class[]
{
Method.class
});
//反射执行start方法
start.invoke(xy,
new
Object[]
{
method
});
//执行要处理对象的原本方法
result
=
method.invoke(this.delegate,
args);
//
反射得到操作者的end方法
Method
end
=
clazz.getDeclaredMethod("end",
new
Class[]
{
Method.class
});
//
反射执行end方法
end.invoke(xy,
new
Object[]
{
method
});
}
catch
(Exception
e)
{
e.printStackTrace();
}
return
result;
}
}
public
class
Test
{
public
static
void
main(String[]
args)
{
IHello
hello
=
(IHello)new
DynaProxyHello().bind(new
Hello(),new
LoggerOperation());
hello.sayGoogBye("Double
J");
hello.sayHello("Double
J");
}
}
当然,不是只有这一个实现方式,java的代理功能只能代理接口,如果要代理类的化,可以使用cglib。
Spring框架当然不会是上述的那么简单(实际上它非常复杂),不过我关注的是核心的实现方式和设计思想。在有些时候,我们不需要使用Spring,甚至不能使用Spring(比如不用Java开发),但是这种思想和方式是可以复用的。使用这种设计思想,按照当前的语言和环境要求,实现自己的IoC和AOP框架。Spring框架(Minjin)Spring框架是一个分层架构,由7个定义良好的模块组成。Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式,如图1所示。图1.Spring框架的7个模块组成Spring框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:核心容器:核心容器提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。Spring上下文:Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能。SpringAOP:通过配置管理特性,SpringAOP模块直接将面向方面的编程功能集成到了Spring框架中。所以,可以很容易地使Spring框架管理的任何对象支持AOP。SpringAOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用SpringAOP,不用依赖EJB组件,就可以将声明性事务管理集成到应用程序中。SpringDAO:JDBCDAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。SpringDAO的面向JDBC的异常遵从通用的DAO异常层次结构。SpringORM:Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO、Hibernate和iBatisSQLMap。所有这些都遵从Spring的通用事务和DAO异常层次结构。SpringWeb模块:Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。所以,Spring框架支持与JakartaStruts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。SpringMVC框架:MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI。Spring框架的功能可以用在任何J2EE服务器中,大多数功能也适用于不受管理的环境。Spring的核心要点是:支持不绑定到特定J2EE服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同J2EE环境(Web或EJB)、独立应用程序、测试环境之间重用。SpringAOP两种实现机制(BaomingChai)SPRING是通过动态代理来实现AOP的,SPRING内部提供了2种实现机制1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理publicObjectgetProxy(ClassLoaderclassLoader){if(logger.isDebugEnabled()){rce().getTargetClass();logger.debug("CreatingJDKdynamicproxy"+(targetClass!=null?"for["+targetClass.getName()+"]":""));}Class[]proxiedInterfaces=AopProxyUtilspleteProxiedInterfaces(this.advised);returnProxy.newProxyInstance(classLoader,proxiedInterfaces,this);}publicObjectproceed()throwsThrowable{//Westartwithanindexof-1andincrementearly.if(this.currentInterceptorIndex==erceptorsAndDynamicMethodMatchers.size()-1){returninvokeJoinpoint();}ObjectinterceptorOrInterceptionAdvice=erceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if(interceptorOrInterceptionAdviceinstanceofInterceptorAndDynamicMethodMatcher){//Evaluatedynamicmethodmatcherhere:staticpartwillalreadyhave//beenevaluatedandfoundtomatch.InterceptorAndDynamicMethodMatcherdm=(InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;if(dm.methodMatcher.matches(this.method,this.targetClass,this.arguments)){returnerceptor.invoke(this);}else{//Dynamicmatchingfailed.//Skipthisinterceptorandinvokethenextinthechain.returnproceed();}}else{//It'saninterceptor,sowejustinvokeit:Thepointcutwillhave//beenevaluatedstaticallybeforethisobjectwasconstructed.return((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);}}2.如果是没有接口声明的类呢?SPRING通过CGLIB包和内部类来实现privatestaticclassStaticUnadvisedInterceptorimplementsMethodInterceptor,Serializable{privatefinalObjecttarget;publicStaticUnadvisedInterceptor(Objecttarget){this.target=target;}publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{ObjectretVal=methodProxy.invoke(target,args);returnmassageReturnTypeIfNecessary(proxy,target,retVal);}}/***Methodinterceptorusedforstatictargetswithnoadvicechain,whenthe*proxyistobeexposed.*/privatestaticclassStaticUnadvisedExposedInterceptorimplementsMethodInterceptor,Serializable{privatefinalObjecttarget;publicStaticUnadvisedExposedInterceptor(Objecttarget){this.target=target;}publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{ObjectoldProxy=null;try{oldProxy=AopContext.setCurrentProxy(proxy);ObjectretVal=methodProxy.invoke(target,args);returnmassageReturnTypeIfNecessary(proxy,target,retVal);}finally{AopContext.setCurrentProxy(oldProxy);}}}/***Interceptorusedtoinvokeadynamictargetwithoutcreatingamethod*invocationorevaluatinganadvicechain.(Weknowtherewasnoadvice*forthismethod.)*/privateclassDynamicUnadvisedInterceptorimplementsMethodInterceptor,Serializable{publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{Objecttarget=advised.getTargetSource().getTarget();try{ObjectretVal=methodProxy.invoke(target,args);returnmassageReturnTypeIfNecessary(proxy,target,retVal);}finally{advised.getTargetSource().releaseTarget(target);}}}/***Interceptorforunadviseddynamictargetswhentheproxyneedsexposing.*/privateclassDynamicUnadvisedExposedInterceptorimplementsMethodInterceptor,Serializable{publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{ObjectoldProxy=null;Objecttarget=advised.getTargetSource().getTarget();try{oldProxy=AopContext.setCurrentProxy(proxy);ObjectretVal=methodProxy.invoke(target,args);returnmassageReturnTypeIfNecessary(proxy,target,retVal);}finally{AopContext.setCurrentProxy(oldProxy);advised.getTargetSource().releaseTarget(target);}}}我们自己也可以来试试1.jdkproxy方式先来一个接口IHelloWorld.javapackagekris.aop.test;publicinterfaceIHelloWorld{publicvoidprint(Stringname);publicvoidwrite(Stringsth);}再来一个实现HelloWorld.javapackagekris.aop.test;publicclassHelloWorldimplementsIHelloWorld{publicvoidprint(Stringname){System.out.println("HelloWorld"+name);}publicvoidwrite(Stringsth){System.out.println("write"+sth);}}代理类DefaultInvocationHandler.javapackagekris.aop.test;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;publicclassDefaultInvocationHandlerimplementsInvocationHandler{/***替换外部class调用的方法*obj外部已经已经包装好InvocationHandler的实例*method外部方法*args方法参数*/publicObjectinvoke(Objectobj,Methodmethod,Object[]args)throwsThrowable{Strings1[]={"kris"};Strings2[]={"anyone"};IHelloWorldihw=newHelloWorld();System.out.println("start!");method.invoke(ihw,args);method.invoke(ihw,s1);Objecto=method.invoke(ihw,s2);System.out.println("stop!");returno;}}测试类Test.javapackagekris.aop.test;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Proxy;publicclassTest{publicstaticvoidmain(Stringargs[]){Classclazz=newHelloWorld().getClass();ClassLoadercl=clazz.getClassLoader();Classclasses[]=clazz.getInterfaces();InvocationHandlerih=newDefaultInvocationHandler();//用InvocationHandler给HelloWorld进行AOP包装IHelloWorldihw=(IHelloWorld)Proxy.newProxyInstance(cl,classes,ih);ihw.print("test");ihw.write("test");}}2.用CGLIB包实现,首先不要忘了引入那个包packagekris.aop.cglib.test;publicclassHelloWorld{publicvoidprint(Stringname){System.out.println("HelloWorld"+name);}publicvoidwrite(Stringsth){System.out.println("write"+sth);}publicvoidprint(){System.out.println("HelloWorld");}}代理类(没用内部类,看起来清楚点)packagekris.aop.cglib.test;importjava.lang.reflect.Method;importxy.MethodInterceptor;importxy.MethodProxy;publicclassMethodInterceptorImplimplementsMethodInterceptor{publicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{System.out.println(method);proxy.invokeSuper(obj,args);returnnull;}}测试类.test;importxy.Enhancer;publicclassTest{publicstaticvoidmain(String[]args){Enhancerenhancer=newEnhancer();enhancer.setSuperclass(HelloWorld.class);//设置回调方法实现类enhancer.setCallback(newMethodInterceptorImpl());//实例化已经添加回调实现的HELLOWORLD实例HelloWorldmy=(HelloWorld)enhancer.create();my.print();}}SpringAOP的底层实现技术(BaomingChai,StephenYu)AOP概述软件的编程语言最终的目的就是用更自然更灵活的方式模拟世界,从原始机器语言到过程语言再到面向对象的语言,我们看到编程语言在一步步用更自然、更强大的方式描述软件。AOP是软件开发思想的一个飞跃,AOP的引入将有效弥补OOP的不足,OOP和AOP分别从纵向和横向对软件进行抽象,有效地消除重复性的代码,使代码以更优雅的更有效的方式进行逻辑表达。AOP有三种植入切面的方法:其一是编译期织入,这要求使用特殊的Java编译器,AspectJ是其中的代表者;其二是类装载期织入,而这要求使用特殊的类装载器,AspectJ和AspectWerkz是其中的代表者;其三为动态代理织入,在运行期为目标类添加增强生成子类的方式,SpringAOP采用动态代理织入切面。SpringAOP使用了两种代理机制,一种是基于JDK的动态代理,另一种是基于CGLib的动态代理,之所以需要两种代理机制,很大程度上是因为JDK本身只提供基于接口的代理,不支持类的代理。基于JDK的代理和基于CGLib的代理是SpringAOP的核心实现技术,认识这两代理技术,有助于探究SpringAOP的实现机理。只要你愿意,你甚至可以抛开Spring,提供自己的AOP实现。带有横切逻辑的实例首先,我们来看一个无法通过OOP进行抽象的重复代码逻辑,它们就是AOP改造的主要对象。下面,我们通过一个业务方法性能监视的实例了解横切逻辑。业务方法性能监视,在每一个业务方法调用之前开始监视,业务方法结束后结束监视并给出性能报告:代码清单2ForumService:包含性能监视横切代码packagexy;
publicclassForumServiceImplimplementsForumService...{
publicvoidremoveTopic(inttopicId)...{
//开始性能监视
PerformanceMonitor.begin("xy.ForumServiceImpl.removeTopic");
System.out.println("模拟删除Topic记录:"+topicId);
try...{
Thread.currentThread().sleep(20);
}catch(Exceptione)...{
thrownewRuntimeException(e);
}
//结束监视、并给出性能报告信息
PerformanceMonitor.end();
}
publicvoidremoveForum(intforumId)...{
//开始性能监视
PerformanceMonitor.begin("xy.ForumServiceImpl.removeForum");
System.out.println("模拟删除Forum记录:"+forumId);
try...{
Thread.currentThread().sleep(40);
}catch(Exceptione)...{
thrownewRuntimeException(e);
}
//结束监视、并给出性能报告信息
PerformanceMonitor.end();
}
}代码清单2中粗体表示的代码就是具有横切特征的代码,需要进行性能监视的每个业务方法的前后都需要添加类似的性能监视语句。我们保证实例的完整性,我们提供了一个非常简单的性能监视实现类,如所示代码清单3所示:代码清单3PerformanceMonitorpackagexy;publicclassPerformanceMonitor{
//通过一个ThreadLocal保存线程相关的性能监视信息
privatestaticThreadLocal<MethodPerformace>performaceRecord=
newThreadLocal<MethodPerformace>();
publicstaticvoidbegin(Stringmethod){
System.out.println("beginmonitor...");
MethodPerformacemp=newMethodPerformace(method);
performaceRecord.set(mp);
}
publicstaticvoidend(){
System.out.println("endmonitor...");
MethodPerformacemp=performaceRecord.get();
mp.printPerformace();//打印出业务方法性能监视的信息
}
}PerformanceMonitor提供了两个方法,begin(Stringmethod)方法开始对某个业务类方法的监视,method为业务方法的签名,而end()方法结束对业务方法的监视,并给出性能监视的信息。由于每一个业务方法都必须单独记录性能监视数据,所以我们使用了ThreadLocal,ThreadLocal是削除非线程安全状态的不二法宝。ThreadLocal中的元素为方法性能记录对象MethodPerformace,它的代码如下所示:代码清单4MethodPerformacepackagexy;
publicclassMethodPerformace{
privatelongbegin;
privatelongend;
privateStringserviceMethod;
publicMethodPerformace(StringserviceMethod){
this.serviceMethod=serviceMethod;
this.begin=System.currentTimeMillis();//记录方法调用开始时的系统时间
}
publicvoidprintPerformace(){
//以下两行程序得到方法调用后的系统时间,并计算出方法执行花费时间
end=System.currentTimeMillis();
longelapse=end-begin;
//报告业务方法执行时间
System.out.println(serviceMethod+"花费"+elapse+"毫秒。");
}
}通过下面代码测试这个拥有方法性能监视能力的业务方法:packagexy;
publicclassTestForumService{
publicstaticvoidmain(String[]args){
ForumServiceforumService=newForumServiceImpl();
forumService.removeForum(10);
forumService.removeTopic(1012);
}
}我们得到以下的输出信息:beginmonitor...
模拟删除Forum记录:10
endmonitor...
xy.ForumServiceImpl.removeForum花费47毫秒。beginmonitor...
模拟删除Topic记录:1012
endmonitor...
xy.ForumServiceImpl.removeTopic花费16毫秒。如实例所示,要对业务类进行性能监视,就必须在每个业务类方法的前后两处添加上重复性的开启性能监视和结束性能监视的代码。这些非业务逻辑的性能监视代码破坏了作为业务类ForumServiceImpl的纯粹性。下面,我们分别
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《中西习语的翻译》课件
- 铁路旅客运输服务到站作业72课件
- 2025年四川省达州市渠县东安雄才学校中考二模语文试题
- 数据库的相关概念课件
- 塑料件的修理方法与步骤陈勇课件
- 双语列车长Bilingualconductor车票票价
- 水泥稳定土中心站集中厂拌法施工马雪姣河北交通课件
- 铁路旅客的服务期望铁路旅客运输服务课件
- 《GB 9078-1996工业炉窑大气污染物排放标准》(2025版)深度解析
- 餐厅装修设计与施工合同范本
- 血液科护士的造血干细胞移植护理
- HGE系列电梯安装调试手册(ELS05系统SW00004269,A.4 )
- 护理教学查房组织与实施
- 小学五年级家长会课件
- 机动车检测站仪器设备日常维护和保养作业指导书
- 立式数控铣床工作台(X轴)设计
- 万千心理情绪障碍跨诊断治疗的统一方案:治疗师指南
- 藏毛窦护理业务查房课件
- 水土保持-新时代水土保持重点工作课件
- 矿井有计划停电停风通风安全技术措施
- 新《用字母表示数》说课
评论
0/150
提交评论