当前位置:编程学习 > JAVA >>

类加载


public class Test_1_2 {

static int b = 9;
static int c;
static {
b = 6;
System.out.println("----------------");
}

public static void main(String[] args) {
System.out.println(Test_1_2.b);
}
}

引用
初始化是类加载的一个步骤,但这个类为什么在被java.exe运行后,在控制台输出了
----------------  之后才进入ClassLoader类呢?

单步执行Test_1_2后在显式赋值的static成员变量及静态初始化块中的变量语句和输出语句处均会
暂停,直到遇到main方法后直接跳至类声明行”public class Test_1_2 {“处暂停,
然后一个stepInto直接跑到ClassLoader中,那么在这次执行过程中这是不是首次进入的
ClassLoader呢?

如果是的话前面静态成员的初始化不需要ClassLoader么?
--------------------编程问答-------------------- 静态块的方法是最先执行的,所以会输出--------,然后执行main方法 输入6 --------------------编程问答--------------------
引用 1 楼 h43857892 的回复:
静态块的方法是最先执行的,所以会输出--------,然后执行main方法 输入6
谢谢关注撒 不过我想问的是用java.exe执行主类后ClassLoader是在输出--------之前
还是之后才执行的呢? 也许debug并不反映底层真实加载情况,但debug一下会发现
已经输出了--------后才进入ClassLoader ,难道说加载中的初始化静态成员部分不需要
类加载器参与吗?  希望我表述清楚了  期待了解的朋友稍微指点一下 --------------------编程问答--------------------
引用 2 楼 tp30512kuang 的回复:
引用 1 楼 h43857892 的回复:

静态块的方法是最先执行的,所以会输出--------,然后执行main方法 输入6
谢谢关注撒 不过我想问的是用java.exe执行主类后ClassLoader是在输出--------之前
还是之后才执行的呢? 也许debug并不反映底层真实加载情况,但debug一下会发现
已经输出了--------后才进入ClassLoader ,难道说……

在初始化static块之前,是有先调用ClassLoader的loadClass方法加载类的,你下载一份源码,断点到Launcher$AppClassLoader.loadClass方法。在初始化static块,打印--------以前,是有进入这个方法,加载类的。 --------------------编程问答-------------------- 先把手头上的事情完成,
再好好看看,why。。。。 --------------------编程问答-------------------- LZ执行一下吧


class AB {
static{
System.out.println("我来了。。。AB");
}
private static AB obj = new AB();
public static int num1 ;

public static int num2 = 0;

private AB() {
System.out.println("我来了。。。AB构造函数");
num1++;
num2++;
// ystem.out.println(+num1);
// ystem.out.println(+num2);
}

public static AB getInstance() {
System.out.println("我来了。。。实例");
return obj;
}
}
public class CsdnTest {
static{
System.out.println("我来了。。。CsdnTest");
}
public static void main(String[] args) {
System.out.println("我来了。。。main");
AB obj = AB.getInstance();
System.out.println("obj.num1=" + obj.num1);
System.out.println("obj.num2=" + obj.num2);
double f = 111231.5585; 
BigDecimal b = new BigDecimal(f); 
double f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println(f1);
}
}

--------------------编程问答-------------------- 简单解释一下:
当你运行java Test_1_2的时候,实际是执行Test_1_2.main(), 当虚拟机启动某个被表明为启动类的类(即含有main方法的那个类)这是一种主动引用。JVM规定了几种主动引用(看这里:JVM Specification - 5.5 Initialization,点这里下载Java 7 版)。
在这种情况下,虚拟机要先初始化这个类。但初始化前先要load,然后link(关于load,link,initialize前看上面的Specification)。
所以:1: load Test_1_2 ---》2: link Test_1_2 --》 3: initialize Test_1_2

看初始化部分,初始化类,简单点说就是按你在类中的书写顺序执行执行那些static变量的初始化和static块。(static变量和static块都按照出现的先后顺序全部放在一个叫<cinit>的方法中。)
在执行static块中的 System.out.println("----------------");时,这里调用了System.out这个static字段。会引起PrintStream(System.out)类的load,link,initialization...

你说先输出"----------------"然后又进入了ClassLoad,但是你打印语句之后在没有需要要加载的类了。。所以我觉得应该不可能。在断点跑到System.out.println("----------------")这句时又会跑进ClassLoader,这时应为要加载PrintStream。
--------------------编程问答--------------------  static 这个修饰的话是成员变量,当类加载的时候,所有的static都会被加载,然后在进main方法
--------------------编程问答--------------------
引用 6 楼 wangfeiwoyun 的回复:
简单解释一下:
当你运行java Test_1_2的时候,实际是执行Test_1_2.main(), 当虚拟机启动某个被表明为启动类的类(即含有main方法的那个类)这是一种主动引用。JVM规定了几种主动引用(看这里:JVM Specification - 5.5 Initialization,点这里下载Java 7 版)。
在这种情况下,虚拟机要先初始化这个类。但初始化前先要load,然后……

是这样的。 --------------------编程问答-------------------- 正解,是在ClassLoader之后执行静态块的

引用 3 楼 smcwwh 的回复:
引用 2 楼 tp30512kuang 的回复:

引用 1 楼 h43857892 的回复:

静态块的方法是最先执行的,所以会输出--------,然后执行main方法 输入6
谢谢关注撒 不过我想问的是用java.exe执行主类后ClassLoader是在输出--------之前
还是之后才执行的呢? 也许debug并不反映底层真实加载情况,但debug一下会发现
已经输出了……



----------------------
http://www.lunwenwa.com/ --------------------编程问答-------------------- 简单的解释:

1、java编译后将所有的static(包括static块,static变量)按顺序全部弄到一个方法里,这个方法叫做<clinit>

2、类load的步骤:装载-连接(验证-准备-解析)-初始化(此时执行<clinit>方法),只有初始化了的类才能使用
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,