您的位置:首页 > 编程语言 > Java开发

Java反射、类加载与垃圾回收

2015-10-11 16:15 387 查看
反射、类加载与垃圾回收

类的加载机制和执行机制是java虚拟机(JVM)的两个最主要的功能。

类的加载机制:虚拟机把描述类的数据从class文件(字节码文件)加载到内存,并对数据进行校验、转换、解析和初始化,最终形成可以被直接使用的java类型。

类的生命周期包括加载(loading)、验证(verification)、准备(preparation)、解析(resolution)、初始化(initialization)、使用(using)、卸载(unloading)等七个阶段,其中验证、准备和解析三个部分统称为连接(linking)。

加载阶段:通过一个类的全限定名(包名+类名)来获取定义此类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行时的数据结构,在java堆中生成一个代表这个类的java.lang.CLass对象,对胃方法区这些数据的访问入口。

验证阶段:不同虚拟机会进行不同类验证的实现,但大致都会完成以下四个阶段的检验过程:文件格式检验(检验字节流是否符合Class文件格式的规范,并能被当前版本的虚拟机处理)、字节码验证(对类方法体进行数据流和控制流分析,保证类的方法在运行是不会做出危害虚拟机的行为)和符号引用验证(发生在将符号引用转化为直接引用的时候,在解析阶段发生)。

准备阶段:正式为类成员变量分配内存,并设置类变量初始值(通常情况下是数据类型的零值,不进行赋值操作)的阶段,这些内存都将在方法区中进行分配。

解析阶段:虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用和内存布局无关,而直接引用的目标必定已经在内存中存在。解析动作主要针对类、字段、类方法、接口方法四类符号引用进行。

初始化阶段:真正开始类中定义的java程序代码(字节码),是执行类构造器的过程。

执行机制:java是通过虚拟机字节码执行引擎完成字节码在虚拟机中的执行操作,不同的虚拟机实现时,执行引擎在执行java字节码可能有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择,也可能两者兼备,甚至可能包含及格不同级别的编译器编译器执行引擎。

反射机制

java反射机制是在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的属性和方法;这种动态获取类的信息以及动态调用对象的方法的功能。

简单说,反射机制指的就是程序在运行时能够获取自身的信息。

反射机制是java中一种强大的工具,主要用于开发框架,如javabean、structs、hibernate和spring框架都大量使用反射机制,对于普通java程序员使用比较少,只作了解。

java反射机制的功能:

1>可以判断运行时的对象所属的类;

2>可以判断运行时对象所具有的成员变量和方法;

3>通过反射机制甚至可以调用对象的private方法

4>通过反射机制可以实例化类的对象。

实现java反射机制的类:

1>Class类:表示正在运行的java应用程序中的类和接口

2>Field类:表示提供有关类或接口的属性信息,以及对它的动态访问权限

3>Constructor类:表示提供关于类的单个构造器的信息以及它的访问权限

4>Mothed类:表示提供关于类或者接口中的某个方法信息

注意:Class类是java反射机制中最重要的功能类,所有获取对象的信息(方法、属性、构造器和访问权限)都需要他来实现。

反射机制的优点:可以动态实例化对象和编译,体现出很大的灵活性。

反射机制的缺点:降低性能,增加复杂度。使用反射机制基本上是一种解释操作,我们可以告诉JVM希望做什么,并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

编写java反射程序的步骤:

1>必须首先获取一个类的Class的对象;

2>然后分别调用Class对象中的方法,配合使用Filed类、Constructor类、Mothed类来获取一个类的属性、方法和构造器的信息;

3>使用reflection API来操作这些信息。

垃圾回收机制

GC回收的触发条件:JVM进行GC回收的频率很高,但因为这种GC占用时间极短,所以对系统产生的影响不大。更值得关注的是GC的触发条件,因为它对系统影响很明显。总体来说有两个条件会触发GC回收:

1>当应用程序空闲时,GC会被调用;

2>java堆内存不足的时候,GC会被调用。

由于是否进行GC回收由JVM根据系统环境决定,而系统环境在不断地变化中,所以GC的运行具有不确定性,无法预计它何时必然出现。

减少GC开销的措施:

1>不要显示频繁调用System.GC()。虽然只是建议而已,但是很多情况下会触发GC回收,从而增加GC的回收频率,降低程序的运行性能;

2>尽量减少临时对象(局部对象)的使用。临时对象(局部对象)是在方法中定义,当方法执行完后这些对象将无效,不能再使用,将会被GC回收;

3>对象不用时最好显示赋值为null,这样有利于GC判断垃圾,从而提高GC的回收效率;

4>尽量使用StringBuffer,而不是String来追加字符;

5>能用基本数据类型(如int,long)尽量不用对应的包装类,也尽量不要频繁的装箱和拆箱;

6>尽量少用静态对象成员变量,因为这些变量属于全局变量,不会被GC回收,他们会一致占用内存,直到程序退出;

7>分散对象实例化或销毁的时间,集中在短时间内实例化大量对象,会导致分配大量内存,JVM在面临这种情况时,会频繁进行GC回收内存或整合内存碎片,从而增加GC的频率。

System.GC():调用System.GC()方法也仅仅是一个请求(或建议)。JVM接收这个请求后,并不是立刻做垃圾回收,而只是对几个垃圾回收算法做了加权,使垃圾回收操作容易发生,或提早发生,或回收较多而已。

finalize()方法:调用该方法用于处理垃圾回收器不能处理的特殊情况。由于垃圾回收器只知道回收显示的由new实例化对象中内存堆中分配的内存空间,而无法回收采用其他方式(如本地化C/C++调用、打开的文件资源等)分配的特殊的内存空间,那么这个时候java允许在类中定义一个finalize()方法来负责回收这块特殊的内存空间。

finalize()方法调用的时机:一旦GC垃圾回收准备好释放对象占用的存储空间,首先会去调用finalize()方法进行一些必要的清理工作。只有到下一次再进行垃圾回收动作的时候,才会真正释放这个对象所占用的内存空间。

finalize()方法的使用:该方法是Object类的方法,使用时需要重写该方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: