对象引用与垃圾收集.ppt

上传人:tian****1990 文档编号:11529669 上传时间:2020-04-27 格式:PPT 页数:68 大小:239KB
返回 下载 相关 举报
对象引用与垃圾收集.ppt_第1页
第1页 / 共68页
对象引用与垃圾收集.ppt_第2页
第2页 / 共68页
对象引用与垃圾收集.ppt_第3页
第3页 / 共68页
点击查看更多>>
资源描述
J2SE,1.4,Tigerflower2005-1,主题,对象引用与垃圾收集异常处理JAVAI/O正则表达式利用JAVA进行XML编程嵌套式类对象的封装与继承抽象类与接口,垃圾收集,垃圾收集器的工作原理是识别程序中不再使用的对象,并且回收其内存。,垃圾收集,J2SE1.4采用的代间收集策略,垃圾收集,JDK1.4的垃圾收集器复制收集器、标记整理收集器、增量式收集器、并行复制收集器、并行清除(scavenging)收集器和并发标记-清除收集器。,垃圾收集,其他收集选项,垃圾收集,观察垃圾收集运行状况有很多办法来监听垃圾回收器的活动。可用Xverbose:gc选项运行JVM,然后观察输出结果一段时间。memory13.009-13.130:GC65536K-16788K(65536K),121.000ms,垃圾收集,微调垃圾收集选项最简单的垃圾收集微调就是扩大最大堆的大小(-Xmx)。随着堆的增大,复制收集会变得更有效,所以在增大堆时,您就减少了每个对象的收集成本。除了增加最大堆的大小,还可以用选项-XX:NewRatio增加分配给年轻代的空间份额。也可以用-Xmn选项显式指定年轻代的大小。,引用对象,从JDK1.2开引入了一个引用对象应用程序接口API允许程序维持一个特别的到对象的引用,这样程序能够通过这一有限的途径和垃圾收集器进行交互。加入引用对象之后的引用与常规引用的区别在于,引用对象中的引用专门由内存管理器来处理。引用对象封装了其它一些对象的引用,我们称之为指示对象。在引用对象创建的同时,也就定义了该引用对象的指示对象。,Heap中的引用对象ReferenceObjects,ReferenceObjects类层次,对象的引用层次,根据对象的可获取程度:强获取、次获取、弱获取、虚获取根据应用程序要求,对象可以是强引用(strongreferences)、次引用(softreferences)、弱引用(weakreferences)、虚引用(phantomreferences)的任意组合。,强引用(strongreference),JVM内存管理器从引用集合出发遍寻堆中所有到对象的路径。当到达某对象的任意路径都不含有引用对象时,则称该对象具有强获取能力。该对象为强引用对象,Rootsetofreferences,strongreferences,garbage,次引用(softreference),次引用(softreference),publicclassDisplayImageextendsAppletSoftReferencesr=null;publicvoidinit()System.out.println(Initializing);publicvoidpaint(Graphicsg)Imageim=(sr=null)?null:(Image)(sr.get();if(im=null)System.out.println(Fetchingimage);im=getImage(getCodeBase(),truck1.gif);sr=newSoftReference(im);System.out.println(Painting);g.drawImage(im,25,25,this);im=null;publicvoidstart()publicvoidstop();,次引用(SoftReference),所有SoftReference到的对象保证会在java虚拟机发生OutOfMemoryError前被清除。SoftReference常被用来实现object-cache(memory-sensitivecaches)之用的。被SoftReference指到的对象,即使没有任何DirectReference,也不会被清除。一直要到JVM内存不足时且没有DirectReference时才会清除,如此一来SoftReference不但可以把对象cache起来,也不会造成内存不足的错误(OutOfMemoryError)。,弱引用(weakreference),当内存管理器未发现strongreferences和softreferences时,我们称对象具有弱获取能力,即在到达该对象的路径中至少包含一个weakreference。,弱引用(weakreference),弱引用(weakreferences)允许用来查询一个对象是否已被垃圾收集器回收。Imageim=(sr=null)?null:(Image)(sr.get();if(im=null)System.out.println(Fetchingimage);im=getImage(getCodeBase(),truck1.gif);sr=newSoftReference(im);,publicclassWeakObjpublicstaticvoidmain(Stringargs)tryReferenceQueueaReferenceQueue=newReferenceQueue();ObjectanObject=newObject();WeakReferenceref=newWeakReference(anObject,aReferenceQueue);StringextraData=newString(ExtraData);HashMapaHashMap=newHashMap();aHashMap.put(ref,extraData);/(key)inaHashMapanObject=null;if(anObject=null)/ClearthestrongreferencetoextraDataextraData=null;catch(Exceptione)System.err.println(Anexceptionoccurred:);e.printStackTrace();,weakreference分析,SoftReference和WeakReference的不同在于前者是否会收集是由垃圾收集器的算法决定的,而后者是一定会被收集的。,虚引用(PhantomReference),主要是用来取代对象的finalize()和WeakReference以及SoftReference最大的不同是:PhantomReference一订要搭配着ReferenceQueue使用,因为PhantomReference的get()传出值一定是null(以避免此对象不小心再度拥有DirectReference)。,Java对象引用接口应用,1.基于Web的应用程序常常要求显示大量图片,当用户离开某一Web页时,往往不能确定是否能够顺利的返回。在这种程序中,应用Java对象引用API可以创建这样一个环境,即当堆内存以最小程度运行时,内存管理器创建对象。当用户返回时,应用程序就会重新载入已经创建的图片。,Java对象引用接口应用,2.应用对象引用队列可以创建这样一个环境,当通过对象引用获得某一对象时,应用程序得到通知。然后,应用程序就可以对相关对象进行清除操作,同时使这些对象在内存管理器中合法化。,内存泄漏,内存泄露的本质是无用但仍被引用的对象。仅当一个对象不再被引用时才能被统计为无用的对象。垃圾收集器只能收集没有被应用程序引用的对象。,无用但仍被引用的对象,上面说明了在Java应用程序执行期间具有不同生存周期的两个类。类A首先被实例化,并会在很长一段时间或程序的整个生存期内存在。在某个时候,类B被创建,类A添加对这个新创建的类的一个引用。现在,我们假定类B是某个用户界面小部件,它由用户显示甚至解除。如果没有清除类A对B的引用,则即便不再需要类B,并且即便在执行下一个垃圾收集周期以后,类B仍将存在并占用内存空间。,内存泄漏无意识的对象保留,publicclassStackprivateObjectelements;privateintsize=0;publicStack(intinitialCapacity)this.elements=newObjectinitialCapacity;publicvoidpush(Objecte)ensureCapacity();elementssize+=e;publicObjectpop()if(size=0)thrownewEmptyStackException();Objectresult=elements-size;returnresult;privatevoidensureCapacity()if(elements.length=size)ObjectoldElements=elements;elements=newObject2*elements.length+1;System.arraycopy(oldElements,0,elements,0,size);,内存泄漏错误的局部作用域,staticStringBuffersb=newStringBuffer();publicstaticStringscopingExample(Stringstring)sb=newStringBuffer();sb.append(hello).append(string);sb.append(,nicetoseeyou!);returnsb.toString();,资源泄漏,释放资源有一个简单的原则:如果有资源清理方法(colse、free)就及时调用。使用finally避免资源泄漏(resourceleaks)finally构件使得某些代码总是得以被执行,无论是否发生异常。在维护对象内部状态和清理non-memory资源方面,finally尤其适用。,资源泄漏被放弃的JDBC对象,Connectionconn=null;tryconn=getConnection();for(inti=0;iNUM_T;i+)Statementstmt=null;ResultSetrs=null;stmt=conn.createStatement();rs=stmt.executeQuery(/*somequery*/);catch(SQLExceptione)/handleanyexceptionsfinallytryif(conn!=null)conn.close();catch(SQLExceptionignor),显示关闭资源,在finally块中显式关闭Connection、Statement和ResultSet对象,以确保无论是在正常还是异常情况下都将所有JDBC对象关闭。tryconn=JNDIUtils.getConnection(DS_NAME);st=con.createStatement();rs=st.executeQuery(query);/对结果集操catch(Exceptione)/handleexceptionfinallyDbUtils.close(rs);DbUtils.close(st);DbUtils.close(conn);,J2EE容器中的连接池,尽管根据JDBC规范的规定,关闭Connection时正常情况下也会将Statement和ResultSet关闭,但不同的提供者都有具体的实现。建议用过资源要及时释放,避免对pool实现的依赖。特别地对于connection执行close时只是将该连接返还给连接池而已。,异常处理异常的继承构架,ThrowableError(严重的系统错误)LinkageErrorThreadDeathVirtualMachineError.ExceptionClassNotFoundExceptionCloneNotSupportedExceptionIllegalAccessException.RuntimeException(执行期异常)ArithmeticExceptionArrayStoreExceptionClassCastException,异常处理,1.可以被抛出。2.可以被捕获。3.可以被程序化地创建。4.可以被JVM创建。5.被表示为第一级对象。6.继承的深度从3开始。7.由String(和来自1.4的StackTraceElements)组成。8.依靠本机方法fillInStackTrace()。,异常处理,异常处理的原则必须对异常有所作为当异常(exception)诞生时,如果你不捉(catch)它,会发生什么事呢?在Java中如果异常产生了却未被捕获,发生异常的那个线程(thread)将因而中断。所以你必须对你的代码所产生的异常有所作为。,异常处理,对异常的可作为方式:1.捕捉并处理它,防止它进步传播(propagate)。2.捕捉并再次抛出它,这么来它会被传播给调用端。3.捕捉它,然后抛出个新异常给调用端。4.不捕捉这个异常,听任它传播给调用端。,异常处理千万不要遮掩异常,publicvoidm1()/.try/CodethatcouldthrowaFileNotFoundExceptioncatch(FileNotFoundExceptionfnfe)/Theexceptionstopshere/.Restofcodeinmethod,异常处理避免极度通用的处理方式,意外地淹没RuntimeExceptiontrydoSomething();catch(Exceptione)log(e);,异常处理理解throws子句,提供throws子句的用意在于,提醒函数调用者,告知可能发生的异常。当你给出throws子句的时候,要填写得完整无缺。虽然编译器不强求这样,但将函数可能抛出的所有异常统统列出,是良好的编程习惯。,异常处理不完整的throws子句,不完整的throws子句使调用者对真实的异常变得难于处理classException1extendsExceptionclassException2extendsException1classException3extendsException2classLazypublicvoidfoo(inti)throwsException1if(i=1)thrownewException1();if(i=2)thrownewException2();if(i=3)thrownewException3();,异常处理Try区段的一个陷阱,最好不要在catch块中返回值classFinallyTestpublicintmethod1()tryreturn2;catch(Exceptione)return3;publicintmethod2()tryreturn3;finallyreturn4;,异常处理不要将异常用于流程控制,将异常用于流程控制会使程序性能低下、含义模糊,难以维护classDoneWithLoopExceptionextendsExceptionclassTestpublicvoidfoo()/.trywhile(true)/Dosomething.if(someloopterminatingcondition)thrownewDoneWithLoopException();catch(DoneWithLoopExceptione)/.,异常处理不要滥用异常,不要针对所有情形使用异常,应该将异常用于符合其意义的地方intdata;MyInputStreamin=newMyInputStream(filename.ext);data=in.getData();while(data!=0)/Dosomethingwithdatadata=in.getData();,异常处理不要滥用异常,应该是面对不可预料的行为,才使用异常。intdata;MyInputStreamin=newMyInputStream(filename.ext);trywhile(true)data=in.getData();/Dosomethingwithdatacatch(NoMoreDataExceptione1),异常处理关于检查型异常和非检查型异常,检查型异常代表关于一个合法指定的请求的操作的有用信息,调用者可能已经对该操作没有控制,并且调用者需要得到有关的通知例如,文件系统已满,或者远端已经关闭连接,或者访问权限不允许该动作。,异常处理关于检查型异常和非检查型异常,对于因为编程错误而导致的异常,或者是不能期望程序捕获的异常(解除引用一个空指针,数组越界,除零,等等),为了使开发人员免于处理这些异常,一些异常被命名为非检查型异常(即那些继承自RuntimeException的异常)并且不需要进行声明。,JAVAI/O,Java语言程序使用的数据必须来自某个地方。通常,这些数据来自一些外部数据源。有许多不同种类的数据源,其中包括数据库、套接字上的直接字节转换和文件等。Java语言提供了许多可以用来从外部数据源获得信息的工具。这些工具大部分都在java.io包中。,JAVAI/O,继承层次,JAVAI/O-文件,File类定义了文件系统上的资源。FileaFile=newFile(temp.txt);aFile.exists();/文件是否存在aFile.createNewFile();/如果File不存在,那么可以创建它:,流,可以使用流访问文件系统上的文件。在最低的级别上,流允许程序接收来自数据源的字节,或者允许将输出发送到目的地。一些流可以处理所有类型的16位字符(类型Reader和Writer)。而其他一些流则只能处理8位字符(类型InputStream和OutputStream)。在这些分层结构中,有几种风格的流(所有流都可以在java.io包中找到)。在最高级别的抽象中,有一些字符流和字节流。,流,字节流,字节流读取(InputStream及其子类)并编写(OutputStream及其子类)8位字节。换句话说,可以将字节流看作是一种更原始的流。因此,也就不难理解为什么关于基本Java语言类的J教程说字节流通常用于二进制数据,比如说图像。以下是一个选定的字节流列表:FileInputStreamFileOutputStream从某一文件中读取文件,以及将字节写入某个文件中。ByteArrayInputStreamByteArrayOutputStream从某个内存数组中读取字节,以及将字节写入某个内存数组中。,字符流,字符流可以读取(Reader及其子类)和写入(Writer及其子类)16位的字符。子类也可以从数据接收器中读取或写入数据,或者处理转换中的字节。以下是一个选定的字符流列表:StringReaderStringWriter这些流从内存中的String中读取或写入字符。InputStreamReaderInputStreamWriter(及其子类FileReaderFileWriter)是字节流与字符流之间的桥梁。Reader风格(flavor)从字节流读取字节,并将它们转换成字符。而Writer风格将字符转换成字节,并将它们放在字节流上。BufferedReader和BufferedWriter在缓冲数据的同时读取或写入另个流,它使读取或写入操作更加有效。可以用缓冲的流包装另一个流。,读取和写入文件,tryFilesource=newFile(input.txt);Filesink=newFile(output.txt);FileInputStreamin=newFileInputStream(source);FileOutputStreamout=newFileOutputStream(sink);intc;while(c=in.read()!=-1)out.write(c);in.close();out.close();catch(Exceptione)e.printStackTrace();,缓冲流写,存在着几种读取和写入File的方法,但是通常,最简便的方法如下所示:1.在File上创建一个FileWriter。2.将FileWriter包装到一个BufferedWriter中。3.只要有必要,可以在BufferedWriter上调用write()来编写File的内容,通常每个行都是以一个行终止符(即n)结尾的。4.在BufferedWriter上调用flush()来清空它。5.关闭BufferedWriter,如果有必要,还需要清除它。代码示例:tryFileWriterwriter=newFileWriter(aFile);BufferedWriterbuffered=newBufferedWriter(writer);buffered.write(Alineoftext.n);buffered.flush();catch(IOExceptione1)e1.printStackTrace();,缓冲流读,Stringline=null;StringBufferlines=newStringBuffer();tryFileReaderreader=newFileReader(aFile);BufferedReaderbufferedReader=newBufferedReader(reader);while(line=bufferedReader.readLine()!=null)lines.append(line);lines.append(n);catch(IOExceptione1)e1.printStackTrace();System.out.println(lines.toString();,正则表达式,正责表达式实质上是一个模式,用于描述共享该模式的一组字符串。例如,以下是一组包含一些常见事物的字符串:astringalongerstringamuchlongerstring这些字符串中的每个字符串都是以“a”开头并以“string”结尾。Stringinput=one,two,threefour,five;Stringresult=input.split(,s+);for(inti=0;iresult.length;i+)System.out.println(resulti);,正则表达式,Java语言的regex功能有三个核心类:Pattern,描述了一个字符串模式。Matcher,测试字符串,查看它是否与模式匹配。PatternSyntaxException。java.lang.Objectjava.util.regex.Matcher(implementsjava.util.regex.MatchResult)java.util.regex.Pattern(implementsjava.io.Serializable),正则表达式-语法,模式语法regex模式描述了表达式试图在输入字符串中查找的字符串的结构。构造什么才是合格的匹配.任何字符?以前的零(0)或壹(1)。*以前的零(0)或其他数字。+以前的壹(1)或其他数字。字符或数字的范围。否定情况(也就是说,“不是”)。d任何数字(可以用0-9替换)。D任何非数字(可以用0-9替换)。s任何空白字符(可以用ntfr替换)。S任何非空白字符(可以用ntfr替换)。w任何单词字符(可以用a-zA-Z_0-9替换)。W任何非单词字符(可以用w替换)。,Pattern类-方法,staticPatterncompile(Stringregex)将给定的正则表达式编译并赋予给Pattern类Matchermatcher(CharSequenceinput)生成一个给定命名的Matcher对象Stringsplit(CharSequenceinput)将目标字符串按照Pattern里所包含的正则表达式为模进行分割.Stringsplit(CharSequenceinput,intlimit)作用同上,增加参数limit目的在于要指定分割的段数,如将limi设为2,那么目标字符串将根据正则表达式分为割为两段.,Pattern类-示例,Stringinput=KevinhasseenLEONsevealtimes,becauseitisagoodfilm.+/凯文已经看过这个杀手不太冷几次了,因为它是一部+好电影。/名词:凯文。;Patternp=Ppile(/+);Stringresult=p.split(input);/p.split(input,3)for(inti=0;iresult.length;i+)System.out.println(resulti);输出:KevinhasseenLEONsevealtimes,becauseitisagoodfilm.凯文已经看过这个杀手不太冷几次了,因为它是一部好电影。名词:凯文。,Pattern类-示例,Patternp=Ppile(/+);Stringresult=p.split(KevinhasseenLEONsevealtimes,becauseitisagoodfilm.+/凯文已经看过这个杀手不太冷几次了,因为它是一部+好电影。/名词:凯文。“,2);for(inti=0;iresult.length;i+)System.out.println(resulti);输出:KevinhasseenLEONsevealtimes,becauseitisagoodfilm.凯文已经看过这个杀手不太冷几次了,因为它是一部好电影。/名词:凯文。,正则表达式匹配,/字符串以a开头,然后是零个或多个字符,最后以string结尾Patternpattern=Ppile(“a.*string”);Matchermatcher=pattern.matcher(astring);booleandidMatch=matcher.matches();System.out.println(是否匹配:+didMatch);intpatternStartIndex=matcher.start();System.out.println(起始索引值:+patternStartIndex);intpatternEndIndex=matcher.end();System.out.println(终止索引值:+patternEndIndex);输出:是否匹配:true起始索引值:0终止索引值:8matches()只告诉我们整个输入顺序是否与模式严格匹配。start()告诉我们所匹配字符串起始的那个字符串中的索引值。end()告诉我们所匹配字符串终止的那个字符串中的索引值,并用该值减去1。,Matcher类方法,StringreplaceAll(Stringreplacement)将目标字符串里与既有模式相匹配的子串全部替换为指定的字符串。StringreplaceFirst(Stringreplacement)将目标字符串里第一个与既有模式相匹配的子串替换为指定的字符串。MatcherappendReplacement(StringBuffersb,Stringreplacement)将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象。StringBufferappendTail(StringBuffersb)将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。booleanfind()尝试在目标字符串里查找下一个匹配子串。booleanlookingAt()检测目标字符串是否以匹配的子串起始。booleanmatches()尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值。,Matcher类-示例,Stringinput=HereisaWikiWordfollowedbyAnotherWikiWord,thenSomeWikiWord.;Patternpattern=Ppile(A-Za-z*(A-Za-z*)+);Matchermatcher=pattern.matcher(input);StringBufferbuffer=newStringBuffer();while(matcher.find()matcher.appendReplacement(buffer,blah$0blah);/matcher.group(0)System.out.println(匹配后的内容为:+buffer);matcher.appendTail(buffer);System.out.println(After:+buffer.toString();输出:匹配后的内容为:HereisablahWikiWordblah匹配后的内容为:HereisablahWikiWordblahfollowedbyblahAnotherWikiWordblah匹配后的内容为:HereisablahWikiWordblahfollowedbyblahAnotherWikiWordblah,thenblahSomeWikiWordblahAfter:HereisablahWikiWordblahfollowedbyblahAnotherWikiWordblah,thenblahSomeWikiWordblah.,正则表达式-组,在每个模式中,通常通过使用圆括号闭包部分模式来创建组:Patternp=Ppile(No.)(.);Matcherm=p.matcher(No.1isfirst,No.2issecond.);while(m.find()System.out.println(该次查找获得匹配组的数量为:+m.groupCount()+匹配字串为:+m.group();for(inti=1;i=m.groupCount();i+)System.out.println(第+i+组的子串内容为:+m.group(i);该次查找获得匹配组的数量为:2匹配字串为:No.1第1组的子串内容为:No.第2组的子串内容为:1该次查找获得匹配组的数量为:2匹配字串为:No.2第1组的子串内容为:No.第2组的子串内容为:2,正则表达式-组,可以通过捕获组来引用匹配项。publicvoidfindWikiWord()Stringinput=HereisaWikiWordfollowedbyAnotherWikiWord,thenSomeWikiWord.HaHa;Patternpattern=Ppile(A-Za-z*(A-Za-z*)+);Matchermatcher=pattern.matcher(input);while(matcher.find()System.out.println(Foundthiswikiword:+matcher.group();输出:Foundthiswikiword:WikiWordFoundthiswikiword:AnotherWikiWordFoundthiswikiword:SomeWikiWordFoundthiswikiword:HaHa,正则表达式-组,替换字符串例子Stringinput=HereisaWikiWordfollowedbyAnotherWikiWord,thenSomeWikiWord.;Patternpattern=Ppile(A-Za-z*(A-Za-z*)+);Matchermatcher=pattern.matcher(input);System.out.println(Before:+input);Stringresult=matcher.replaceAll(“blah$0blah”);/matcher.group(0)System.out.println(After:+result);输出:Before:HereisaWikiWordfollowedbyAnotherWikiWord,thenSomeWikiWord.After:HereisablahWikiWordblahfollowedbyblahAnotherWikiWordblah,thenblahSomeWikiWordblah.,嵌套式类,1,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!