Java中类的加载、连接和初始化
Java中类的加载、连接和初始化
类的加载、连接和初始化
先介绍一下JVM和类
JVM和类:
当我们调用Java命令运行某个Java程序时,该命令将会启动一个Java虚拟机进程,不管该Java程序有多么复杂,该程序启动的所有线程,所有变量都处于该Java虚拟机进程里,它们都使用该JVM进程的内存区。当系统出现以下几种情况时,JVM进程将被终止。
1. 程序运行到最后正常结束;
2. 程序运行到使用System.exit()或Runtime.getRuntime().exit()代码处结束程序;
3. 程序运行过程中遇到未捕获的异常或者错误而结束;
4. 程序所在的平台强制结束了JVM进程。
从以上看出,当程序运行结束时,JVM进程结束,该进行在内存中的状态将会丢失。如下例:
// 定义A类含有静态Field a
public class A
{
public static int a = 6;
}
// 定义B类创建A类的实例
public class B
{
A a1 = new A();
a1.a++;
System.out.println(a1.a); // 输出7
}
// 定义B类创建A类的实例
public class C
{
A a2 = new A();
System.out.println(a2.a); // 输出6
}
C类中输出6的原因是:B与C是两次运行JVM进程,B运行完后对A所做的修改全部丢失,第二次运行JVM时将再次初始化A类。
类的加载:
系统可能在第一次使用某个类时加载该类,也可能采用预加载机制来加载某个类。
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化3个步骤来对该类进行初始化,如果没有意外,JVM将会连接完成这3个步骤,所有有时也把这3个步骤统称为类加载或者类初始化。
类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象,也就是说,当程序使用任何类时,系统都会为之建立一个java.lang.Class对象
(每个类是一批具有相同特征的对象的抽象,而系统中所有的类实际上也是实例,它们都是java.lang.Class的实例)。
类的加载由类加载器完成,类加载器通常由JVM提供,这些类加载器也是所有程序运行的基础,JVM提供的这些类加载器通常被称为系统类加载器,除此之外,我们也可以通过继承ClassLoader基类来创建自己的类加载器,通过使用不同的类加载器,可以从不同来源加载类的二进制数据,通过有如下几种来源。
1. 从本地文件系统加载class文件;
2. 从Jar包加载class文件;
3. 通过网络加载class文件;
4. 把一个class源文件动态编译,并执行加载。
类的连接:
当类被加载之后,系统为之生成一个对应的Class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到JRE中,类连接可分为3个阶段:
1. 验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致;
2. 准备:类准备阶段则负责为类的静态Field分配内存,并设置默认初始值;
3. 解析:将类的二进制数据中的符号引用替换成直接引用。
类的初始化:
在类的初始化阶段,虚拟机负责对类进行初始化,主要就是对静态Field进行初始化,在Java类中对静态Fieldr指定初始值有两种方式:1. 声明静态Field时指定初始值;2. 使用静态初始化块为静态Field指定初始值。如:
public class Test
{
static int a = 5;
static int b;
static int c;
static
{
b = 6;
}
}// 最终结果 a=5,b=6,c=0
静态初始化块被当成类的初始化语句,JVM会按这些语句在程序中的排列顺序依次执行它们,如:
public class Test
{
static
{
b = 6;
}
static int a = 5;
static int b = 9;
}// 最终结果 a=5,b=9
JVM初始化一个类包含如下几个步骤:
1. 假如这个类还没有被加载和连接,则程序先加载并连接该类;
2. 假如该类的直接父类还没有被初始化,则先初始化其直接父类(直接父类也依次执行1,2,3 保证类依赖的所有父类都会被初始化);
3. 假如类中有初始化语句,则系统依次执行这些初始化语句。
类初始化的时机:
1. 创建类的实例,包括使用new操作符来创建,通过反射来创建,通过反序列化的方式来创建;
2. 调用某个类的静态方法;
3. 访问某个类或者接口的静态Field,或者为该静态Field赋值;
4. 通过反射方式来强制创建某个类或接口对应的java.lang.Class对象,例如,Class.forName(“Person”),如果系统还未初始化Person类,则这行代码将会导致该Person类被初始化,并返回Person类对应的java.lang.Class对象;
5. 初始化某个类的子类;
6. 直接使用java.exe命令来运行某个主类。
另外:对于一个Field型的静态Field,如果该Field的值在编译时就可以确定下来,那么这个Field相当于“宏变量“,Java编译器会在编译时直接把这个Field出现的地方替换成它的值,因为即使程序使用该静态Field,也不会导致该类的初始化。
Java中类的加载、连接和初始化的更多相关文章
- java 中类的加载顺序(转)
1.虚拟机在首次加载Java类时,会对静态初始化块.静态成员变量.静态方法进行一次初始化 2.只有在调用new方法时才会创建类的实例 3.类实例创建过程:按照父子继承关系进行初始化,首先执行父类的初始 ...
- 从经典面试题看java中类的加载机制
1.概述 类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助. 由于Ja ...
- Java 中类的加载顺序
如果类A和类B中有静态变量,静态语句块,非静态变量,非静态语句块,构造函数,静态方法,非静态方法,同时类A继承类B,请问当实例化A时,类内部的加载顺序是什么? 测试代码如下: Class B: pub ...
- java中类的加载顺序介绍(ClassLoader)
转自:http://blog.csdn.net/eff666/article/details/52203406 1.ClassNotFoundExcetpion 我们在开发中,经常可以遇见java. ...
- java中类的加载情况
当一个类存在继承且与其他类有关联情况时,类中各模块加载顺序如下: 1.首先找到public类,判断该类是否继承其他类,如果没有继承其他类(Object类除外),则加载该类:否则转去加载该类的超类,超类 ...
- java中类的加载过程和对象的创建过程
1.类加载过程 首先,jvm在执行时,遇到一个新的类,会先去内存的方法区中去寻找该类的.class文件,如果找到了就直接运行,如果没有找到,则会去硬盘中去寻找该类的.class文件,并将该类文件加载到 ...
- JAVA类的加载、连接与初始化
JAVA类的加载.连接与初始化 类的声明周期总共分为5个步骤1.加载2.连接3.初始化4.使用5.卸载 当java程序需要某个类的时候,java虚拟机会确保这个类已经被加载.连接和初始化,而连接这个类 ...
- java类从加载、连接到初始化过程
类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用. 每个类编译后产生一个Class对象,存储在.class文件中,JV ...
- Java类的加载、链接和初始化
一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样 ...
随机推荐
- Subversion服务器搭建
如何快速建立Subversion服务器,并且在项目中使用起来,这是大家最关心的问题,与CVS相比,Subversion有更多的选择,也更加的容易,几个命令就可以建立一套服务器环境,可以使用起来,这里配 ...
- c程序代码优化的一些方法
我认为一个好的用于科学计算的程序代码应该:算法漂亮精妙,程序简洁易懂,运算快速,节省内存.这里有的地方是矛盾的,比如简洁vs易懂,时间vs空间,找个平衡吧.目前来看时间要比空间宝贵一些.写程序分几步: ...
- SQL Server 索引分类
什么是索引 拿汉语字典的目录页(索引)打比方:正如汉语字典中的汉字按页存放一样,SQL Server中的数据记录也是按页存放的,每页容量一般为4K .为了加快查找的速度,汉语字(词)典一般都有按拼音. ...
- jQuery中each的用法之退出循环和结束本次循环
jQuery中each的用法之退出循环和结束本次循环 jQuery中each类似于javascript的for循环 但不同于for循环的是在each里面不能使用break结束循环,也不能使用conti ...
- 08-Java 多线程编程
1.Java多线程-线程与进程的区别 (1)线程:程序中单独依靠程序进行运行 线程是程序中的顺序控制流,只能使用分配给程序的资源和环境. (2)进程:执行中的程序 一个进程可以包含一个或多个线程. 一 ...
- 【转】如何让DIV水平和垂直居中
来源:http://blog.163.com/www.wxs_123/blog/static/82784664201321831746921/ 我们在设计页面的时候,经常要把DIV居中显示,而且是相对 ...
- MySQL数据库update更新子查询
比如: ? 1 2 3 4 UPDATE test.tb_vobile a set a.name = '111 ' WHERE a.id = (select max(id) id from test. ...
- js 实现返回上一页和刷新等页面跳转功能
原文 出处http://www.2cto.com/kf/201111/109821.html 1. Javascript 返回上一页history.go(-1), 返回两个页面: history.go ...
- android数据存储之File
android中使用File进行存储主要使用到OpenFileOutput和OpenFileInput两个方法,下面直接用一个例子来说明一下. (1)布局文件main.xml文件 <?xml v ...
- 【性能诊断】十、性能问题综合分析(案例1,windbg、Network Monitor)
[问题描述]: 产品中某业务功能A,在进行"刷新"->选择制单->新增->切换其他行等一系列操作后,突然发生客户端不响应的现象. 经反复测 ...