`
m635674608
  • 浏览: 5041471 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

jvm 初始化

 
阅读更多
package test;

public class A {
	private static A a = new A();

	private B b = B.getInstance();

	private A() {

	}

	public static A getInstance() {
		System.out.println("A被调用");
		return a;
	}

	public void test() {
		System.out.println(b);
	}
}

 

package test;

public class B {
	private static B b = new B();

	private A a = A.getInstance();

	private B() {

	}

	public static B getInstance() {
		System.out.println("B被调用");
		return b;
	}

	public void test() {
		System.out.println(a);
	}
}

 

package test;


/**
 * 面先说一下环境,比如现在有两个类,A和B,两个类都是单例类,这个时候如果A有个B的实例变量,B有个A的实例变量,
 * 会发生什么情况呢?开始我以为会出现栈溢出。但是让我迷惑的是,居然没问题。只是其中一个类的 实例变量会是NULL。
 * 下面看代码。 

 * @author zhang_zengmin
 *
 */
public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		B b = B.getInstance();
		b.test();
		System.out.println("==========");
		A a = A.getInstance();
		a.test();

		// A a = A.getInstance();
		// a.test();
		// System.out.println("==========");
		// B b = B.getInstance();
		// b.test();
		// System.out.println("==========");
		/**
		 * 1.类Test的main()方法的B.getInstance()生成的invokestatic指令触发了类B的初始化 
			2.执行类B的<clinit>方法的过程中,显式调用了B自己的<init>方法(static b = new B()) 
			3.B的<init>方法中,调用A.getInstance()生成的invokestatic指令触发了A的初始化(private A a = A.getInstance()) 
			4.执行A的<clinit>方法的过程中调用了A自己的<init>方法(static a = new A()) 
			5.类A的<init>方法中需要调用B.getInstance(),但是虚拟机中一个类(<class,classloader>为一个类)只会初始化一次,因此不会再触发B的初始化,既不会再执行B.<clinit>方法。 
			6.那由a.<init>触发的B.getInstance()被执行,输出第一行“B被调用”,B.getInstance()方法结束。虽然这时候B的初始化阶段尚未结束,但是解析阶段已经完成,所以getInstance()方法可以被正确执行,但这时候静态字段static B b仍然为null(注意,b.<init>方法还没完呢),所以这个B.getInstance()方法返回值为null,所以A.b为null。 
			7.A.<clinit>方法结束,第3步的invokestatic指令正式执行,即A.getInstance()被执行,输出第二行“A被调用”,返回A的实例,这时候B.a不为null了。 
			8.B.<clinit>方法结束,第1步的invokestatic指令正式执行,即B.getInstance()被执行,输出第三行“B被调用” 
			9.B.test()方法被执行,输出B.a的toString()方法结果,即第四行“A@35ce36”。 
			10.A.getInstance()方法被执行,输出第五行“A被调用”。 
			11.A.test()方法被执行,输出null,即A.b的值。 
		 */
	}

}

 

分享到:
评论

相关推荐

    JVM面试反馈.pdf

    - **JVM初始化步骤**:包括加载、验证、准备、初始化和使用。 - **类初始化的时机**:类加载后,首次主动使用类时(如创建类实例、访问静态字段、调用静态方法等)会触发初始化。 - **JVM结束生命周期的情况**:程序...

    IBM JVM参数选项

    - `init`: 输出JVM初始化时的信息。 - 示例:`-verbose:class` 6. **-version**: 显示JVM的版本信息。 - 示例:`-version` #### 高级参数 1. **-D**&lt;property&gt;=&lt;value&gt;: 设置系统属性。 - 示例:`-Dfile....

    Java静态初始化块和对象初始化块

    静态初始化块是以`static`关键字标识的代码块,它在类被加载到Java虚拟机(JVM)时执行,且只执行一次。静态初始化块常用于设置类级别的变量,或者执行只应执行一次的初始化操作。例如,如果一个类需要在程序运行前...

    如何配置Tomcat的JVM虚拟机内存大小

    - `-Xms`:JVM初始化堆的大小,即虚拟机启动时向系统申请的初始内存大小。 - `-Xmx`:JVM堆的最大值,定义了虚拟机可以使用的最大内存空间。 合理设置这两个参数对于避免内存溢出和提高应用性能极为重要。通常,...

    如何设置Tomcat的JVM虚拟机内存大小

    -Xms 用于设置 JVM 初始化堆的大小,-Xmx 用于设置 JVM 堆的最大值。这些值的大小一般根据需要进行设置。初始化堆的大小执行了虚拟机在启动时向系统申请的内存的大小。一般而言,这个参数不重要。但是有的应用程序在...

    java程序初始化顺序

    在Java编程语言中,程序初始化的顺序是一个关键概念,它涉及到类加载、对象创建以及执行流程的安排。了解这些顺序对于编写高效、无错误的代码至关重要。以下是对Java程序初始化顺序的详细说明: 1. **类加载阶段**...

    java代码的初始化顺序demo

    如果多个线程同时尝试初始化同一个类,JVM会保证类的初始化仅执行一次。这是通过类锁实现的,确保了线程安全。 在分析`init`目录中的文件时,你可以看到这些概念的实际应用。例如,可能会有一个类包含静态和非静态...

    Java虚拟机JVM类加载初始化

    Java虚拟机JVM类加载初始化是Java程序运行过程中的关键环节,它负责将类的字节码文件加载到内存中并进行相应的处理,以便程序能够正确执行。在Java中,类加载器(Classloader)扮演着核心角色。下面将详细讨论类加载...

    java JVM 类加载-初始化 过程

    java JVM 类加载-初始化 过程

    java中类的初始化顺序

    1. **静态成员变量的初始化**:当类被加载到JVM中时,静态成员变量首先被初始化。 2. **静态初始化块的执行**:紧随静态成员变量之后,静态初始化块被执行。 3. **父类静态成员变量及初始化块**:如果当前类继承自另...

    Java初始化块Java初始化块.doc

    这意味着静态初始化块在类被加载到JVM中时执行,而不是在创建每个对象时执行。静态初始化块主要用于初始化类级别的变量,即静态变量。由于它是在类加载时执行,所以它总是在任何对象创建之前运行。静态初始化块不能...

    探究java的ClassLoader及类变量初始化顺序

    之后,类的初始化(初始化阶段)才会进行,包括执行静态初始化块和设置静态变量。 ClassLoader的层次结构通常包括Bootstrap ClassLoader(启动类加载器)、Extension ClassLoader(扩展类加载器)和AppClassLoader...

    javaservice工具源码

    5. **错误处理**:源码中包含了对各种可能的错误情况的处理,比如JVM初始化失败或Java程序执行异常,这些都会通过Windows服务的错误处理机制报告。 6. **服务卸载**:当不再需要服务时,JavaService提供了卸载服务...

    javalauncher

    7. **处理异常**:如果在启动过程中出现错误,如找不到主类、JVM初始化失败等,Java Launcher会捕获这些异常并显示相应的错误信息。 Java Launcher的灵活性允许开发者通过各种方式定制应用程序的启动行为,例如通过...

    Java类的加载连接和初始化实例分析

    JVM初始化类的步骤可以分为五步:首先,假如这个类还没有被加载和连接,程序先加载并连接该类。其次,假如该类的直接父类还没有被初始化,则先初始化其直接父类。然后,假如类中有初始化语句,则系统依次执行这些...

    深入Java初始化.pdf

    `&lt;clinit&gt;`方法就是JVM在类加载时用于执行这些初始化操作的特殊方法。它在类被首次加载时调用,且只调用一次。在上述代码示例中,`debug.MyTest`类中的静态变量`i`除以0导致`ArithmeticException`,异常信息显示在`...

    java 知识点总结

    1. **命令行启动应用时由JVM初始化加载**。 2. **通过`Class.forName()`方法动态加载**。 3. **通过`ClassLoader.loadClass()`方法动态加载**。 其中,`Class.forName()`和`ClassLoader.loadClass()`的主要区别在于...

    深入java虚拟机(三)——类的生命周期(下)类的初始化1

    在Java虚拟机(JVM)中,类的初始化会在类加载和连接完成后发生。 初始化阶段的目标是确保类的静态成员被正确地初始化。有两种主要的方式进行类的初始化: 1. **静态变量的声明处赋值**:这是最直接的方式,如`...

    类初始化和实例初始化1

    当Java虚拟机(JVM)首次遇到某个类的实例或者静态变量,或者当类的静态方法被调用时,会触发类的加载和初始化。类的初始化主要涉及到以下几个步骤: 1. 类加载:JVM会通过类加载器将类的.class文件加载到内存中。 ...

Global site tag (gtag.js) - Google Analytics