明确初始化过程以及变量生命周期对于内存优化以及高并发有重要意义,好比哪些变量须要声明成为类变量,哪些能够是局部变量,有效避免向前引用及线程安全等。html
1、类初始化过程(即开辟内存空间)分析:数组
在JVM中 ,对于同一个JVM 来讲 每一个类至对应一个Class(类)对象 也就是类只加载一次,(开辟一段内存空间),可是每次建立一次实例对象 就会建立一个实例对象,也就是实例化屡次。而且每次实例化过程当中都不会 再实例化类成员。 类成员(也就是static修饰的)老是初始化在实例(也就是对象)成员以前( 这一点很重要如下均按照这个规律进行的初始化)。 1.一个类中包含: 变量:类变量, 成员变量,方法内局部变量。 方法:静态方法(类方法),普通方法。 构造方法。静态初始化块 ,初始化块。 2.当类加载时如下内容会优先被建立: 类变量 ,静态初始化块 ,类方法。 以及其余方法信息。加载顺序按照书写顺序。 3.类建立对象时如下内容按照顺序被初始化 首先初始化成员变量和初始化块,这二者是平等关系,初始化按照书写顺序。 再初始化 构造方法。 4.对于含有继承关系的类来讲调用子类的属性或者方法的时候, 都会对其父类进行初始化,初始化过程是找到最高父类,从最高父类开始 依次进行初始化。安全
2、类中变量生命周期:并发
类成员:类加载以后存在,程序结束以后消失。 成员变量:实例建立开始 到实例 回收。 方法(静态块,非静态块)内变量:跟随方法(静态块,非静态块)调用开始 到方法结束消亡。高并发
3、关于变量在内存中存储位置分析:优化
内存分区:在JVM虚拟机中,内存能够粗糙的划分为 方法区 堆区 栈区 。
若考虑详细内存分配能够参考文章:http://www.cnblogs.com/dingyingsi/p/3760447.html(深刻理解JVM—JVM内存模型)。 对于栈区:每一个方法开始执行时 ,在栈上开辟栈帧 ,栈是线程私有的,存储方法的局部变量等方法信息,方法执行结束则栈帧出栈即销毁。所以许多文章提到 局部变量储存在栈。 对于堆:Java 堆是被全部线程共享的一块内存区域,在虚拟机启动时建立。堆上存放着全部的引用类型实例,包括对象实例和数组。当实例对象失去引用时,则会被垃圾回收,也就意味着生命周期结束,这里存在一种特殊状况,Java 内存泄漏,当某个对象被两个或多个引用指向时,只销毁其中一个引用,则容易引起内存泄漏。 对于方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。即时编译后的代码我理解为常量池,和字面量。常量池存放了最典型的是字符串,好比声明字符串 String a = “a”; “a” 会被存储在常量池中,再次声明String b = “a”;则是直接从常量池中抓取。线程