类加载,初始化

java虚拟机与程序的生命周期

1.java虚拟机结束生命周期的原因

1.执行system.exit()方法。

2.程序正常执行结束。

3. 程序在执行过程中遇到了异常或错误终止。

4.由于操作系统出现错误而导致java虚拟机进程终止。

2.类的加载、连接与初始化

加载:查找并加载类的二进制数据。类的加载时将类的.class文件中的二进制数据读入到内存中,将其存放到数据区的方法区中,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。加载.class文件的方式:从本地系统中直接加载;通过网络下载.class文件;从zip.jar等归档文件中加载.class文件;从专用数据库中提取.class文件;将java源文件动态编译成.class文件

类的加载的最终产品是位于堆区中的Class对象;class对象封装了类在方法区内的数据结构,并且向java程序员提供了访问数据结构的接口。

连接:验证:确保被加载的类的正确性。

准备: 为类的静态变量分配内存,并将其初始化为默认值。

解析:把类中的符号引用转换为直接引用。

初始化:为类的静态变量赋予正确的初始值。

3. java程序对类的使用方式可分为两种,主动使用和被动使用;所有的java虚拟机实现必须在每个类或者接口被java程序首次主动使用时才初始化他们。java的主动使用主要分为6中方式:

创建类的实例;

访问某个类或接口的静态变量,或者对该静态变量赋值;

调用类的静态方法;

反射(class.forName("com.test"))

初始化一个类的子类

java虚拟机启动时被标明为启动类的类

除了以上6中情况,其他情况下都属于被动使用,都不会引起类的初始化。

4.类的加载

  有两种类型的类加载器

java虚拟机自带的加载器:根类加载器(Bootstrap)、扩展类加载器(Extension)、系统类加载器(System)

用户自定义的类加载器 :java.lang.ClassLoader的子类;用户可以定制类的加载方式

JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中就遇到了.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类才报告错误(LinkageError错误);如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误。

class Singleton{

public static int counter1;
public static int counter2=0;
private static Singleton singleton = new Singleton();
private Singleton(){
counter1++;
counter2++;
}
public static Singleton getInstance(){
return singleton;
}
}
class Test{

}
public class JvmTest1 {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(Singleton.class.getClassLoader());

System.out.println("counter1 = " + singleton.counter1);
System.out.println("counter2 = " + singleton.counter2);
}
}

执行main方法中,调用了singleton 的静态方法,为静态变量分配分配空间并且赋给默认值,其中 singleton 为null,counter1 为0,counter2为0,然后进行初始化,调用singleton 的构造方法,导致counter1 =1,counter2=1;然后counter1没有初始化还是1,counter2初始化为0,所以最终结果是

[email protected]
counter1 = 1
counter2 = 0

class Singleton{

public static int counter1;
public static int counter2=0;
private static Singleton singleton = new Singleton();
private Singleton(){
counter1++;
counter2++;
}
public static Singleton getInstance(){
return singleton;
}
}
class Test{

}
public class JvmTest1 {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(Singleton.class.getClassLoader());

System.out.println("counter1 = " + singleton.counter1);
System.out.println("counter2 = " + singleton.counter2);
}
}

同理可分析

[email protected]
counter1 = 1
counter2 = 1

5.类的初始化

类的初始化步骤:

1.加入这个类没有被加载和连接,那就先进行加载和连接

2.加入类存在直接的父类,并且这个父类还没有被初始化,那就先初始化直接的父类。

3. 假如类中存在初始化语句,那就依次执行这些初始化语句。

注意:1.final类型的编译常量不会到时类的初始化。

2.当java虚拟机初始化一个类时,要求他的所有父类都已经被初始化,但是这条规则并不适用于接口。

在初始化一个类时,并不会先初始化它所实现的接口。

在初始化一个接口时,并不会先初始化它的父接口。

因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态变量时,才回导致该接口的初始化。

3.只有当程序访问的静态变量或静态方法确实在当前类或者当前接口中定义时,才可以认为是对类或接口的主动使用。

类加载,初始化

时间: 2024-07-30 16:14:22

类加载,初始化的相关文章

深入Java虚拟机JVM类加载初始化学习笔记

1. Classloader的作用,概括来说就是将编译后的class装载.加载到机器内存中,为了以后的程序的执行提供前提条件. 2. 一段程序引发的思考: 风中叶老师在他的视频中给了我们一段程序,号称是世界上所有的Java程序员都会犯的错误. 一般不假思索的结论就是,a=1,b=1.给出的原因是:a.b都是静态变量,在构造函数调用的时候已经对a和b都加1了.答案就都是1.但是运行完后答案却是a=1,b=0. 为什么呢,这3句无非就是静态变量的声明.初始化,值的变化和声明的顺序还有关系吗?Java

类加载-初始化的触发

 对于初始化阶段,虚拟机规范严格规定了有且只有5种情况必须立即对类进行“初始化” .这5种场景中的行为称为对一个类进行主动引用.除此之外,所有引用类的方式都不会触发初始化,称为被动引用.  1)遇到new.getstatic.putstatic 或invokestatic 这4 条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化.生成这4 条指令的最常见的Java 代码场景是:使用new 关键字实例化对象的时候.读取或设置一个类的静态字段(被final 修饰.已在编译期把结果放入常量池

彻头彻尾理解单例模式与多线程

摘要: 本文首先概述了单例模式产生动机,揭示了单例模式的本质和应用场景.紧接着,我们给出了单例模式在单线程环境下的两种经典实现:饿汉式 和 懒汉式,但是饿汉式是线程安全的,而懒汉式是非线程安全的.在多线程环境下,我们特别介绍了五种方式来在多线程环境下创建线程安全的单例,使用 synchronized方法.synchronized块.静态内部类.双重检查模式 和 ThreadLocal 实现懒汉式单例,并总结出实现效率高且线程安全的单例所需要注意的事项. 版权声明: 本文原创作者:书呆子Rico

什么是热修复?

插件化和热修复技术是Android开发中比较高级的知识点,是中级开发人员通向高级开发中必须掌握的技能,插件化的知识可以查我我之前的介绍:Android插件化.本篇重点讲解热修复,并对当前流行的热修复技术做一个简单的总结. 热修复 什么是热修复? 简单来讲,为了修复线上问题而提出的修补方案,程序修补过程无需重新发版! 技术背景 在正常软件开发流程中,线下开发->上线->发现bug->紧急修复上线.不过对于这种方式代价太大.  而热修复的开发流程显得更加灵活,无需重新发版,实时高效热修复,无

java设计模式之--单例模式

前言:最近看完<java多线程编程核心技术>一书后,对第六章的单例模式和多线程这章颇有兴趣,我知道我看完书还是记不住多少的,写篇博客记录自己所学的只是还是很有必要的,学习贵在坚持. 单例模式,也就是一个类只有一个实例,任何对象要访问这个类只能通过这个实例对象来访问,我们把房子比喻一个java类,每个房子只有一把钥匙(好比每个类只有一个实例),这样唯有房子的主人才有这个钥匙才能访问房子,其他人访问不了. 我们来看一下怎么写一个单例模式的java代码,方法有很多种: 1.立即加载(也叫饿汉模式)

写一个单例(Singleton),并说明单例的目的和好处

单例的目的:保证一个类只有单一的实例,也就是说你无法通过new来创建这个类的一个新实例. 单例的好处:当一个对象在程序内部只能有一个实例的时候,它可以保证我们不会重复创建,而是始终指向同一个对象. Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问. 第一种:在声明变量时实例化(也叫饿汉式单例模式),代码如下: public class Singleton { private s

【SpringBoot】1.SpringBoot介绍

一.SpringBoot产生的契机我们知道,搭建一个Spring+Struts+Hibernate(SSH)架构或Spring+SpringMVC+MyBatis(SSM)架构的应用,基本上都需要以下步骤:(1)配置Maven依赖(2)配置数据库properties配置文件,日志properties文件(3)配置Spring核心类加载文件bean.xml,其中会配置:    a.properties配置引入    b.包扫描    c.数据源(数据库连接池)    d.数据库会话工厂    e.

回客科技 面试的 实现ioc 容器用到的技术,简述BeanFactory的实现原理,大搜车面试的 spring 怎么实现的依赖注入(DI)

前言:这几天的面试,感觉自己对spring 的整个掌握还是很薄弱.所以需要继续加强. 这里说明一下spring的这几个面试题,但是实际的感觉还是不对的,这种问题我认为需要真正读了spring的源码后说出来的东西才有意义.这种面试的问法,也只能是面试的问法,对实际的掌握还是没有丝毫意义的.所以我认为 有机会一定要读下spring的源码 来过一遍 具体实现,这样的才是有意义的做法.同意的请举手. 这里说明一下这三个spring 面试问题: 1.回客科技 面试的 实现ioc 容器用到的技术 第1种 说

JavaSE 第二次学习随笔(二)

循环结构中的多层嵌套跳出 targeta: for(int i = 0; i < 100; i++){ for (int j = 0; j < 100; j++) { if(i + j == 100){ // break targeta; continue targeta; } } } 数组 * 一维数组里边存的是值(直接数据) 二维数组里边存的是一维数组的地址 * 二维数组和一维数组一样都是数据类型 二维数组类型的构成: 数据类型 + [] + [] 创建格式 type [][] name

设计模式(1)——单例模式

在Java开发过程中,很多场景下都会碰到或要用到单例模式,在设计模式里也是经常作为指导学习的热门模式之一,相信每位开发同事都用到过.我们总是沿着前辈的足迹去做设定好的思路,往往没去探究为何这么做,所以这篇文章对单例模式做了详解. 一.单例模式定义 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 二.单例模式的特点: 单例模式类只能有一个实例 单例类必须自己创建唯一实例 给其他类访问提供接口 单例模式保障了对象的唯一性,在计算机系统中,线程池.缓存.日志对象.对话框.打印