java程序运行过程和内存分析
此篇文章是个人看了一些资料得出的总结,如有不准确,烦请指正。仅供参考。
Java程序运行分析概括
当运行一个Java 程序时。需要经过编译和运行两个阶段。而这里涉及到的内存,是指在运行时,程序的内存划分。编译阶段由编译器将Java文件编译成字节码文件。而运行一个程序时,首先会启动一个java虚拟机进程。java虚拟机包括类装载器和执行引擎。然后进行 加载 - 连接 - 初始化这三个过程。这里区分一下初始化和实例化这两个概念。初始化是针对类的,而实例化是针对对象的。下面粗略概览一下运行过程。
- 编译阶段
将java文件由编译器编译为字节码文件 - 运行阶段
1、加载
通过类的名称获取字节码文件的二进制字节流,并转换为静态存储结构存放于方法区,并生成唯一的class对象。作为访问方法区中该数据类型的访问接口。
2、连接
-验证:确保被加载类的正确性(即使编译正确,但字节码文件也有可能被修改)
-准备:为类的静态变量分配内存,并将其初始化为默认值。
-解析:把类的符号引用转换为直接引用。
3、初始化
为类的的初始化赋予正确的初始值和分配内存空间,初始化一般通过显示的直接赋值,或通过静态静态代码块内将类变量赋值。类变量存放于方法区。
内存分析
java运行时内存划分主要分为五个区域。
ps:下图从其他博客中引用。
- 方法区
存放运行时的唯一元素,如字节码文件,类变量,还有常量池。
- 虚拟栈
当每调用一个方法时,都会创建一个栈帧。
- 程序计数器
记录程序走到了哪一步。
- 堆
存放对象本身。
- 本地方法区
其实和虚拟机栈是一样的存储结构,也是存放方法栈帧,只是这个方法是本地方法。
这里还是通过一个例子分析显得直观一些。
案例分析
class Insect{
private int i=9;
protected int j;
Insect(){
System.out.println("i="+i+",j="+j);
j=39;
}
private static int x1=printInit("static Insect.x1.initialized");
static int printInit(String string) {
// TODO Auto-generated method stub
System.out.println(string);
return 47;
}
}
public class Battle extends Insect {
private int k=printInit("Bettle.k initizlized");
public Battle(){
System.out.println("k="+k);
System.out.println("j="+j);
}
private static int x2=printInit("statc battel.x2 initialize");
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("battel constructor");
Battle b = new Battle();
/*
* 类加载完成后再创建对象
* 当编译器加载Battle类时,发现它有Insect基类,先加载Insect,所以先打印第一句
* 然后加载Battle,发现静态成员,打印第二句
* 然后执行入口函数,打印第三局
* 创建对象时,向外扩展,先创建基类对象(成员先初始化,在执行构造函数)
*
*/
}
}
运行时内存分析如下:
大概就是这样了,如果有不对的,烦请指正。谢谢。
来源:CSDN
作者:橄榄粒
链接:https://blog.csdn.net/Goblin_E/article/details/104054267