java程序的执行过程

//
程序执行过程:
1. Load到内存区。
在硬盘上有一块程序代码,要想运行,编译好的东西load到内存。然后操作系统代码找到

main方法,然后执行。

2. 找到main方法开始执行。
3. 执行过程中的内存管理。
一般分为四部分:
a. code segment: 存放代码,代码区
b. data segment: 静态变量,字符串常量
c. stack(栈): 局部变量
d. heap(堆): new出来的东西

1.Java程序执行包括加载类和实例化类两个阶段。
2.加载类阶段与实例化类阶段都是按照先父类后子类的顺序进行。
3. 加载类完成,立即形成Class类的一个对象,名字就是所加载类的类名,然后,该Class类的对象完成所加载类的静态成员的初始化。
4.JVM 启动的时候就加载了Class类,并且分配空间,完成了相关的初始化。
5.一个类的静态成员并不存在于new出来的堆区空间中,而是存在该类对应的Class类对象的空间里。


1.将程序编译成字节码的不是JDK;
JDK的全拼是java development kit,就是java开发工具包。
包括一些函数库或编译程序之类的。
将程序编译成字节码的应该是JVM。
2.你在从main函数开始,执行一个程序的时候,一个JVM实例也随之产生,
它的任务就是执行java程序,可以说JVM开始于一个main函数。
JVM启动后执行你的java程序,JVM加载并解析你在程序里写的类(已经被编译成.class了)。
3.静态变量在类被加载的时候被初始化。


///
class parent
{
int i = 9;//定义初始化
int j;
parent()
{
System.out.println("i = " + i);
j = 39;
System.out.println("j = " + j);
}
static int x = prt("static parent.x initialized.");//静态定义初始化
static int prt(String s)
{
System.out.println(s);
return 47;
}
}

public class getToKnowConstructingOrder extends parent
{
int k = prt("getToKnowConstructingOrder.k initialized.");//定义初始化
getToKnowConstructingOrder()
{
prt("k = " + k);
prt("j = " + j);
}
static int y = prt("getToKnowConstructingOrder.y initialized.");//静态定义初始化
static int prt(String s)
{
System.out.println(s);
return 63;
}
public static void main(String[] args)
{
prt("getToKnowConstructingOrder constructor.");
getToKnowConstructingOrder s = new getToKnowConstructingOrder();
}
}

执行结果:static parent.x initialized. 1

getToKnowConstructingOrder.y initialized. 2

getToKnowConstructingOrder constructor. 3

i = 9 4

j = 39 5

getToKnowConstructingOrder.k initialized. 6

k = 63 7

j = 39 8

详细运行过程分析:首先,要执行getToKnowConstructingOrder里面的main,需要加载main所在的.class文件,在加载的过程中,JVM发现getToKnowConstructingOrder有父类的,所以转入首先加载parent类的.class文件,形成parent类对象,实现对parent类中静态成员的初始化,于是出现了结果1,然后parent类的.class文件加载完毕,重新回来继续完成加载getToKnowConstructingOrder类的.class文件,形成getToKnowConstructingOrder类对象,该对象对getToKnowConstructingOrder类中的静态成员完成初始化,出现了结果2。

由于执行main函数需要的所有类的.class文件都已经完成了加载,开始执行main函数,于是出现了结果3,要实例化一个getToKnowConstructingOrder实例(即完成非静态成员的定义初始化,接着完成调用构造函数),必须先实例化一个parent类(即完成非静态成员的定义初始化,接着完成调用构造函数),于是出现了结果4,5,此时父类的实例化完成,回来接着进行子类的实例化,于是出现了结果6,7,8。

这里还有一些细节:子类不会自动调用父类的静态方法,除非用super.prt()。

Java程序执行包括加载类和实例化类两个阶段。

加载类阶段与实例化类阶段都是按照先父类后子类的顺序进行。

加载类完成,立即形成Class类的一个对象,名字就是所加载类的类名,然后,该Class类的对象完成所加载类的静态成员的初始化。

JVM启动的时候就加载了Class类,并且分配空间,完成了相关的初始化。

一个类的静态成员并不存在于new出来的堆区空间中,而是存在该类对应的Class类对象的空间里。

/


Java code
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->
public class Test{
private static Test tester = new Test(); //step 1
private static int count1; //step 2
private static int count2 = 0; //step 3
public Test(){ //step 4
count1++;
count2++;
System.out.println("" + count1 + count2);
}
public static Test getTester(){ //step 5
return tester;
}

public static void main(String[] args){
Test.getTester();
}



问:以上代码执行的顺序~,输出的结果~

这是我昨天面试时碰到的一题,我尽量还原了原题。先说一下,这里count1未初始化可不是我忘了,原题就是这么搞D~
正好我对这种带有自身类型的字段的情况有些迷糊,索性答曰:“有变量未初始化,编译器可能会报错”~

我想问的是,如果忽略未初始化错误的话,以上代码执行顺序到底如何?


0
顶1
踩 分享到:
羊车问题的讨论---四种思路 .
2012-02-28 08:49:05浏览 140评论(7)分类:编程语言相关推荐
评论
7 楼 buptwhisper 2 小时前
其实这个也好弄清楚的,你在每一个可能的地方打上断点,然后debug,你就大致上懂了。
6 楼 wmswu 2 小时前
这种类型的面试题 还真不少啊.......
5 楼 H小阿飞 3 小时前
程序是没有错误的,对于定义的int类型的字段,未初始化的情况下,默认是0。
至于执行顺序,由于一开始就对Test进行了实例化,所以先执行test()方法,然后执行main方法,最后执行getTester()方法。
如果程序改成private static Test tester;而在main方法中对Test进行实例化:Test.getTester(); tester = new Test();这样的话,test()方法就是最后执行。
上面也说了,int类型的count1未初始化,则默认是0,所以countl和count2 ++ 后,结果都是1,输出结果加了"",所以输出的是一个String类型的字符串,输出结果为11
4 楼 m635674608 3 小时前
燈小嗨 写道
JAVA类首次装入时,开始加载静态变量和静态块,也就是说会首先为静态区域分配内存空间,此时tester、count1、count2都已经分配空间,其中tester为一个引用空间,count1、count2为默认值0。
第二步开始执行 private static Test tester = new Test() 这段代码,调用构造器打印出count1、count2 分别为 1 和 1 。然后依次执行一下代码 private static int count1; private static int count2 = 0; 此时,count2被重置为0,因此如果此时再次打印的话count1、count2的值应该为 1 和 0 。
估计是楼主的题目记忆有问题,这题考察的重点应该在于count被重置后的结果,代码应该不是这样的。

嗯。。这位仁兄解说的正确。。。。。。
3 楼 燈小嗨 3 小时前
JAVA类首次装入时,开始加载静态变量和静态块,也就是说会首先为静态区域分配内存空间,此时tester、count1、count2都已经分配空间,其中tester为一个引用空间,count1、count2为默认值0。
第二步开始执行 private static Test tester = new Test() 这段代码,调用构造器打印出count1、count2 分别为 1 和 1 。然后依次执行一下代码 private static int count1; private static int count2 = 0; 此时,count2被重置为0,因此如果此时再次打印的话count1、count2的值应该为 1 和 0 。
估计是楼主的题目记忆有问题,这题考察的重点应该在于count被重置后的结果,代码应该不是这样的。
2 楼 lixieinstein 3 小时前
结果就是11,编译不会报错,count1没有初始化但是会自动初始化为0
1 楼 smiky 3 小时前
忽略未初始化错误的话会首先加载静态代码及其代码块,在Test.getTester()执行之前会执行new操作,然后在调用此方法
好久没看JAVA基础了,希望没说错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值