首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

java程序的实施过程

2012-06-26 
java程序的执行过程/////////////////////////////////////////////////////////////////////////////////

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基础了,希望没说错



热点排行