本文将分析java命令运行.class文件的处理过程。
1、什么时候开始处理?
虚拟机如何触发处理某一.class文件?归结起来,当调用某类的static成员或方法时便启动.class处理过程。需要注意的是static方法包括三种:main方法、显式申明的static方法、构造器。加上static成员即4种情况会触发.class处理。
2、如何处理?
虚拟机接收到处理任务后,首先需要查询该.class是否加载,若尚未加载,则启动加载.class任务。然后根据需要触发实例化任务。
为表述方便,做以下约定:
- 用boolean isLoaded(class c) 判断该.class是否已经加载
- 用initObj(Class c) 表示实例化某类对象。
processClass(Class c,boolean needInitObj){
if !isLoaded(c) loadClass(c); //已加载则跳过 详见2.1
if needInitObj initObj(c);
}
2.1 加载.class任务过程--loadClass(c)
为表述方便,做以下约定:
- 用loadClass(class c) 表示加载任务,其中参数c表示要加载的类;
- 用class c.getSupper() 表示获取c的直接父类;
- 用processStaticArea(Class c)表示处理c的静态区域代码,可能包含:类静态成员初始化,类的静态代码(static {});
- 用Statement 表示语句,exe()方法表示执行该语句;
- 用getStatement(Class c)表示获取静态处理区域的语句集 ;
- 用class[] getClass(statement),表示获取语句中的他类集(出自身外的他类)。
则其加载过程描述如下:
loadClass(Class c){
loadClass(c.getSupper()); //加载直接父类
processStaticArea(c); //处理静态区域
}
静态处理模拟代码
processStaticArea(Class c){
Statement[] ss=getStatament(c);
for(Statement s:ss){
Class[] cs=getClass(s);
for(Class cc:cs) loadClass(cc);
s.exe();
}
}
2.2 实例化过程
为表述方便,做以下约定:
- 用initObj(Class c) 表示实例化C的对象;(构造函数中的首行(若无显式的调用父类的构造函数则将调用父类无参构造函数作为首行))
- 用initVarAndCode(Class c)表示初始化成员变量和代码区({})
- 用runStructor(Class c)表示执行执行构造器。(不包括首行(即排除父类构造))
实例化过程描述如下:
initObj(Class c){
initObj(c.getSupper());
initVarAndCode(c); //若碰到新的类,则loadClass(newClass);
runStructor(c);
}
3.验证试验
Print.java 代码
//Print.java
import java.io.*;
public class Print {
static String str_print=printStr("static var in print");
public static void print(Object obj) {
System.out.println(obj);
}
public static String printStr(String str){
System.out.println(str);
return str;
}
}
Print2.java 代码
//Print2.java
import java.io.*;
public class Print2 {
static {
System.out.println("static code in Print2");
}
static String s=printStr("static var in Print2");
public static String printStr(String str){
System.out.println(str);
return str;
}
public static void print(Object obj) {
System.out.println(obj);
}
public static int printInt(int i) {
System.out.println(i);
return i+1;
}
public static void print() {
System.out.println();
}
} ///:~
Sandwich2.java 代码
//Sandwich2.java
class Bread extends Cheese {
int j=Print.printInt(25);
static int i=Print.printInt(15);
static int i1=Print.printInt(16);
Bread() {super("test"); Print.print("Bread(),i="+i); }
}
class Cheese {
Cheese() { Print.print("Cheese()"); }
Cheese(String str) { Print.print("Cheese(str) :"+str); }
}
class Lettuce {
Lettuce() { Print.print("Lettuce()"); }
}
/////////
class Meal {
static {
System.out.println("static code in Meal");
}
static String str_Meal=Print2.printStr("static var in Meal");
String str_Meal_var =Print2.printStr("var in Meal");
Meal() { Print2.print("Meal()"); }
Meal(int k) { Print2.print("Meal(),k="+k); }
}
class Lunch extends Meal {
String str_Lunch_var =Print2.printStr("var in Lunch");
{
System.out.println("code in Lunch");
}
static {
System.out.println("static code in Lunch");
}
static String str_Lunch=Print2.printStr("static var in Lunch");
Lunch() { super(1);Print.print("Lunch()"); }
}
class PortableLunch extends Lunch {
static String str_Meal=Print2.printStr("static var in PortableLunch");
static {
System.out.println("static code in PortableLunch");
}
{
System.out.println("code in PortableLunch");
}
PortableLunch() { Print.print("PortableLunch()");}
}
public class Sandwich2 extends PortableLunch {
static {
System.out.println("static code in Sandwich2");
}
static String str_Meal=Print2.printStr("static var in Sandwich2");
private Bread b = new Bread();
private Lettuce l = new Lettuce();
public Sandwich2() { Print.print("Sandwich()"); }
public static void main(String[] args) {
new Sandwich2();
new Sandwich2();
}
}
水平有限,欢迎指出错误;
欢迎转载,请注明出处,并提供到博客园本文的链接。

浙公网安备 33010602011771号