《第九章、Java中类生命周期与java垃圾回收机制.ppt》由会员分享,可在线阅读,更多相关《第九章、Java中类生命周期与java垃圾回收机制.ppt(33页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、复习java异常处理机制:知识回顾异常处理的一般步骤:异常抛出异常捕获异常处理1.异常处理是由try、catch与finally三个关键字所组成的程序块2.异常类可分为两大类,分别为java.lang.Exception与java.lang.Error类。3.如何一个方法可能会出现异常,且方法内有没有任何的try-catch-finally块来捕异常时,可以在方法声明处用throws子句来声明抛出异常。相比较相比较try-catch捕获异常来讲,这种处理异常的方式较消极,所以有时候也该方式叫做异常的捕获异常来讲,这种处理异常的方式较消极,所以有时候也该方式叫做异常的消极处理方式,消极处理方式,
2、管管try-catch捕获异常捕获异常叫做叫做积极处理方式积极处理方式4.Throws和throw的区别第九章、JAVA生命周期和垃圾回收机制首先来了解一下jvm(java虚拟机)中的几个比较重要的内存区域,这几个区域在java类的生命周期中扮演着比较重要的角色:方法区:方法区:在java的虚拟机中有一块专门用来存放已经加载的类信息、常量、静态变量以及方法代码的内存区域,叫做方法区。常量池:常量池:常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信息。堆区:堆区:用于存放类的对象实例。栈区:栈区:也叫java虚拟机栈,是由一个一个的栈帧组成的后进先出的栈式结构,栈桢中存放方法运行时产
3、生的局部变量、方法出口等信息。当调用一个方法时,虚拟机栈中就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失,如果方法中调用了其他方法,则继续在栈顶创建新的栈桢。java类的生命周期当我们编写一个java的源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到卸载的全过程。一个java类的完整的生命周期会经历加载、连接、初始化、使用(即对象生命周期)、和卸载五个阶段在加载阶段,java虚拟机会做什么工作呢?其实很简单,就是找到需要加载的类并把类的信息加载到jvm的方
4、法区中,然后在堆区中实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口。类的加载方式比较灵活,我们最常用的加载方式有两种,一种是根据类的全路径名找到相应的class文件,然后从class文件中读取文件内容;另一种是从jar文件中读取。加载阶段是类的生命周期中的第一个阶段,加载阶段之后,是连接阶段。有一点需要注意,就是有时连接阶段并不会等加载阶段完全完成之后才开始,而是交叉进行,可能一个类只加载了一部分之后,连接阶段就已经开始了。但是这两个阶段总的开始时间和完成时间总是固定的:加载阶段总是在连接阶段之前开始,连接阶段总是在加载阶段完成之后完成。加载加载连接阶段比较复杂,
5、一般会跟加载阶段和初始化阶段交叉进行,这个阶段的主要任务就是做一些加载后的验证工作以及一些初始化前的准备工作,可以细分为三个步骤:验证、准备和解析。连接连接验证准备解析连接验证验证:验证:当一个类被加载之后,必须要验证一下这个类是否合法,比如这个类是不是符合字节码的格式、变量与方法是不是有重复、数据类型是不是有效、继承与实现是否合乎标准等等。总之,这个阶段的目的就是保证加载的类是能够被jvm所运行。准备:准备:准备阶段的工作就是为类的静态变量分配内存并设为jvm默认的初值,对于非静态的变量,则不会为它们分配内存。有一点需要注意,这时候,静态变量的初值为jvm默认的初值,而不是我们在程序中设定的
6、初值。jvm默认的初值是这样的:基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。引用类型的默认值为null。常量的默认值为我们程序中设定的值,比如我们在程序中定义finalstaticinta=100,则准备阶段中a的初值就是100。连接准备解析:解析:这一阶段的任务就是把常量池中的符号引用转换为直接引用。那么什么是符号引用,什么又是直接引用呢?我们来举个例子:我们要找一个人,我们现有的信息是这个人的身份证号是1234567890。只有这个信息我们显然找不到这个人,但是通过公安局的身份系统,我们输入1234567890这个号之
7、后,就会得到它的全部信息:比如湖北省武汉市武汉大学张三,通过这个信息我们就能找到这个人了。这里,123456790就好比是一个符号引用,而湖北省武汉市武汉大学张三就是直接引用。在内存中也是一样,比如我们要在内存中找一个类里面的一个叫做show的方法,显然是找不到。但是在解析阶段,jvm就会把show这个名字转换为指向方法区的的一块内存地址,比如c17164,通过c17164就可以找到show这个方法具体分配在内存的哪一个区域了。这里show就是符号引用,而c17164就是直接引用。在解析阶段,jvm会将所有的类或接口名、字段名、方法名转换为具体的内存地址。连接解析初始化初始化在初始化阶段,JA
8、VA虚拟机执行类的初始化语句,为类的静态变量赋予初始值。在程序中,静态变量的初始化有两种途径:1、在静态变量的声明处进行初始化2、在静态代码块中进行初始化。publicclassInitClasspublicstaticStringa=“nihao”;/静态变量的声明处进行初始化static/在静态代码块中进行初始化。System.out.println(初始化InitClass);静态变量的声明语句,以及静态代码块都被看做类的初始化语句,java虚拟机会按照初始化语句在文件中的先后顺序来依次执行他们。如果有父类,则首先按照顺序运行父类中的变量赋值如果有父类,则首先按照顺序运行父类中的变量赋值
9、语句和静态语句语句和静态语句。Demo1Demo2在类的初始化阶段,只会初始化与类相关的赋值语句和静态语句,在类的初始化阶段,只会初始化与类相关的赋值语句和静态语句,也就是有也就是有static关键字修饰的信息关键字修饰的信息,没有,没有static修饰的赋值语句和静态语修饰的赋值语句和静态语句在实例化对象的时候才会运行。句在实例化对象的时候才会运行。使用(对象生命周期)当类初始化完成后,根据类信息在堆区中实例化类对象,初始化非静态变量、非静态代码以及默认构造方法,创建对象创建对象对象的使用对象的使用清除对象清除对象创建对象创建对象通过创建一个对象可创建类的一个实例,也称实例化此类。例Rect
10、anglerect=newRectangle();创建一个对象包括三部分:声名部分实例化部分初始化部分1、对象声明对象声明并不创建新的对象。例:Rectanglerect;2、实例化对象实例化对象操作符new通过为新对象分配存储空间来实例化类格式:new类的构造方法例newRectangle(100,200);Rectanglerect=newRectangle(100,200);3、初始化对象初始化对象每个类都至少有一个构造函数,当创建对象时调用指定的构造函数来初始化对象例Rectanglerect=newRectangle();Rectanglerect=newRectangle(100,
11、200);在定义类时如未定义构造函数系统,java会自动构造一个没有参数的构造函数。对象的使用使用对象包括:从对象中获得信息改变对象的状态使对象执行某些操作实现途径:引用对象的变量调用对象的方法引用对象变量引用对象变量的格式的格式:对象引用.对象的变量SubInitClass2aClass2=newSubInitClass2();intb=aClass2.num;调用对象的方法调用对象的方法格式:对象引用.对象方法名();或对象引用.对象方法名(参数表);例Field2field2=newField2();field2.Method();清除对象清除对象java运行使系统有一个垃圾回收进程负责
12、清除不再使用的对象。垃圾回收器垃圾回收器垃圾回收器定期扫描内存,对于被应用的对象加上标记,按可能的路径扫描结束后清除未加标记的对象。被回收的对象是:不再被任何引用变量引用的对象引用变量自动放弃人为地将引用变量置为nullfinialize()方法()方法在一个对象被垃圾回收器回收之前,java解释器会自动调用对象的finalize()方法。通常在该方法内包括了释放系统资源的代码段。finalize()方法在类java.lang.Object中实现如:protectedvoidfinalize()throwsthrowable/cleanupcodeforthisclasssuper.final
13、ize();/清除对象使用的所有资源,包括由于继/承关系而获得的资源卸载卸载在类使用完之后,如果有下面的情况,类就会被卸载:该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。加载该类的ClassLoader已经被回收。该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。如果以上三个条件全部满足,jvm就会在方法区垃圾回收的时候对类进行卸载,类的卸载过程其实就是在方法区中清空类信息,java类的整个生命周期就结束了。垃圾回收机制垃圾回收是Java程序设计中内存管理的核心概念,JVM的内存管理机制被称为垃圾回收机制。一个对象创建后
14、被放置在一个对象创建后被放置在JVM的堆内存中,当永远不再引用这个对象时,它的堆内存中,当永远不再引用这个对象时,它将被将被JVM在堆内存中回收。被创建的对象不能再生,同时也没有办法通过程序在堆内存中回收。被创建的对象不能再生,同时也没有办法通过程序语句释放它们。语句释放它们。在做在做Java应用开发时经常会用到由应用开发时经常会用到由JVM管理的两种类型的内存:堆内存和管理的两种类型的内存:堆内存和栈内存。简单来讲,堆内存主要用来存储程序在运行时创建或实例化的对象与栈内存。简单来讲,堆内存主要用来存储程序在运行时创建或实例化的对象与变量。例如通过变量。例如通过new关键字创建的对象。而栈内存
15、则是用来存储程序代码中声关键字创建的对象。而栈内存则是用来存储程序代码中声明为静态或非静态的方法。明为静态或非静态的方法。堆内存在堆内存在JVM启动的时候被创建,堆内存中所存储的对象可以被启动的时候被创建,堆内存中所存储的对象可以被JVM自动回收,自动回收,不能通过其他外部手段回收,也就是说开发人员无法通过添加相关代码的手段来回不能通过其他外部手段回收,也就是说开发人员无法通过添加相关代码的手段来回收堆内存中的对象。收堆内存中的对象。堆内存通常情况下被分为两个区域:新对象区域与老对象区域。堆内存通常情况下被分为两个区域:新对象区域与老对象区域。新对象区域:保存新创建的对象新对象区域:保存新创建
16、的对象老对象区域:在老对象区域中的对象仍然会有一个较长的生命周期,经过一段时老对象区域:在老对象区域中的对象仍然会有一个较长的生命周期,经过一段时间后,被转入老对象区域的对象,就变成了垃圾对象。此时,它们都被打上相应的间后,被转入老对象区域的对象,就变成了垃圾对象。此时,它们都被打上相应的标记,标记,JVM系统将会自动回收这些垃圾对象系统将会自动回收这些垃圾对象堆内存主要用来存储程序在运行时创建或实例化的对象与变量。例如通过new关键字创建的对象。而栈内存则是用来存储程序代码中的方法。补充知识补充知识:内部类内部类内部类(Innerclass)是定义在另一个类中的类。当A类为B类服务时,为不让
17、外界直接访问到A类,可把这个A类定义在B类的内部,变为内部类。内部类的基本语法:修饰符class外部类修饰符class内部类/内部类的类体public class Parcel1 class Destination private String label;Destination(String whereTo)label=whereTo;String readLabel()return label;/在类的的函数中使用内部类在类的的函数中使用内部类,与使用普通类没多大区别与使用普通类没多大区别 public void ship(String dest)Destination d=new Des
18、tination(dest);System.out.println(d.readLabel();public static void main(String args)Parcel1 p=new Parcel1();p.ship(Hello);在外部类外访问内部类的基本语法如下所示。Wai.Neiwn=newWai().newNei();使用该方法就能够创建一个内部类对象,使用该内部类对象就可以访问内部类的成员。该方法是不容易理解的,该方法也是可以分为两条语句的。Waiw=newWai();Wai.Neiwn=w.newNei();这样就很容易理解了。首先是创建一个外部类的对象,然后让该外部类
19、对象调用创建一个内部类对象。classWaiclassNei/内部类inti=5;/内部类成员intii=6;publicclassNeiBuLei3publicstaticvoidmain(Stringargs)Wai.Neiwn1=newWai().newNei();Waiw=newWai();Wai.Neiwn2=w.newNei();System.out.println(内部类中的变量i的值为:+wn1.i);System.out.println(内部类中的变量ii的值为:+wn2.ii);注意事项:注意事项:内内部部类类作作为为外外部部类类的的一一个个成成员员存存在在,与与外外部部类
20、类的的属属性性、方方法法并并列列。内内部部类不能与外部类重名。类不能与外部类重名。Java编编译译器器在在创创建建内内部部类类对对象象时时,隐隐式式的的把把其其外外部部类类对对象象的的引引用用也也传传了了进进去去并并一一直直保保存存着着。因因此此一一个个内内部部类类对对象象可可以以访访问问创创建建它它的的外外部部类类对对象象的内容,甚至包括私有变量。的内容,甚至包括私有变量。在在外外部部类类中中不不能能直直接接访访问问内内部部类类的的成成员员,必必须须通通过过内内部部类类的的实实例例去去访访问问。通通过过内内部部类类的的实实例例,外外部部类类可可以以访访问问内内部部类类的的所所有有成成员员,无
21、无论论其其访访问问修修饰是什么。饰是什么。外外部部只只能能被被public或或是是默默认认修修饰饰。而而内内部部类类可可以以被被privateprotected默默认认public修饰。修饰。内内部部类类与与外外部部类类一一旦旦编编译译成成功功,就就会会成成为为完完全全不不同同的的两两类类。对对于于一一个个名名为为outer的的外外部部类类和和其其内内部部定定义义的的名名为为inner的的内内部部类类。编编译译完完成成后后出出现现outer.class和和outer$inner.class两类。两类。class Outer private int a=-100;void testInnerMe
22、thod()Inner inner=new Inner();inner.display();class Inner /Inner被定义为内部类被定义为内部类 void display()System.out.println(显示显示:outer_exp=+a);public class InnerClassDemo public static void main(String args)Outer outer=new Outer();outer.testInnerMethod();外部类的成员可以在内部类中使用外部类的成员可以在内部类中使用在外部类中必须通过内部类实例访问内部类方法:在外部类中
23、必须通过内部类实例访问内部类方法:classOuterprivateInnerTooltool=newInnerTool();publicclassInnerTool/内部类内部类publicintinneradd(inta,intb)returna+b;publicintadd(inta,intb)returntool.inneradd(a,b);publicclassTesterpublicstaticvoidmain(Stringargs)Outerouter=newOuter();/其实是使用内部类来完成相加操作的。其实是使用内部类来完成相加操作的。inta=outer.add(2,3
24、);System.err.println(a=+a);Outer.InnerTooltool=newOuter().newInnerTool();a=tool.inneradd(2,3);/功能是一样的功能是一样的,注意上面的初始化方法注意上面的初始化方法System.err.println(a=+a);classOuterintouter_exp=-100;voidtestInnerMethod()Innerinner=newInner();inner.display();classInner/Inner被定义为内部类被定义为内部类intY=100;voiddisplay()System.o
25、ut.println(显示显示:outer_exp=+outer_exp);voidshowY()System.out.println(Y=+newInner().Y);/error内部类成员只有在内部类内可知,且不能被外部类使用。如何处理,才能使用内部成员?知识总结1、一个java类的完整的生命周期会经历加载、连接、初始化、使用(即对象生命周期)、和卸载五个阶段2、加载:找到需要加载的类并把类的信息加载到jvm的方法区中,然后在堆区中实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口。3、连接:主要任务就是做一些加载后的验证工作以及一些初始化前的准备工作,可以细分为三个步骤:验证、准备和解析。4、初始化:JAVA虚拟机执行类的初始化语句,为类的静态变量赋予初始值5、使用:对象的生命周期(创建对象、对象的使用、清除对象)6、卸载、类使用完之后,如果有下面的情况,类就会被卸载:7、java自带垃圾回收机制8、补充内部类知识:内部类(Innerclass)是定义在另一个类中的类。外部类的成员可以在内部类中使用、在外部类中必须通过内部类实例访问内部类方法、内部类成员只有在内部类内可知,且不能被外部类使用。下一章节:下一章节:JAVA输入输入输出系统输出系统有难度,做好预习有难度,做好预习
限制150内