最近实训,从java基础讲起,向我们介绍了jvm的运行机制,以及java的字节码文件在内存中做了什么,怎么做的。
一、堆、栈与方法区
堆是用于存放对象的,是一个二叉树结构,它为对象开辟属性空间和方法空间,属性空间的大小有属性的数据类型决定,方法空间则默认为四个字节,它存放的是对方法的引用。堆内存在使用完后不会自动释放,java的GC负责对堆内存清理。
栈是方法执行的工作空间,是一个线性结构,它按照线程划分栈帧,用于方法的操作。它会存放局部变量,形参,断点,临时数据,堆空间及方法区空间地址。当执行方法时,就是在栈区开辟空间,方法执行完,空间就自动释放。
方法区分为代码区,静态区和常量池,代码区用来存放字节码文件和共享代码,其中共享代码需要通过对象来访问,它又是与类绑定的。静态区放带有static关键字的数据,大小与数据类型有关,它与类关联。常量池又叫常量缓冲区,它里面放置了-128~127的(integer)整形数据和字符串对象(当你创建一个字符串时,系统会先到字符串池找,有,就把它的地址赋给字符串,没有,就在字符串常量池,创建一个,把地址个字符串)。
贴上helloworld
public class HelloWorld {
public static void main(String[] args)
{
String s ;
s = “Hello World!”; //定义字符串s
System.out.println(s);
}
}
了解了堆、栈和方法区,我们通过cmd找到文件路径,javac .java文件,系统会从环境变量找到java配置的path,在java的bin目录找到javac程序,javac会通过程序的main方法让jvm进入编译,对.java。文件进行编译,如无语法语义错误,将java文件编译成字节码文件,而在执行java指令的过程(是解释的过程)中,通过public权限的类(主类),虚拟机找到所有出现的类的class文件(对于系统类库的类,它会去环境变量的classpath下找),将class文件加载到方法区的代码区,static关键字找到主方法,为main方法在栈开辟栈帧,到String[] args,为其在堆区开辟一块空间,空间没有内容。String s是方法内的局部变量,会在方法的工作空间开辟一块内存,为四个字节,初始为垃圾值,用于存放地址。当s="Hello World!"时,jvm会去常量池找有没有"Hello World!",如果没有,把它加入常量池,把它的地址赋予s,有则直接赋予地址。
System.out.println(s);这句语句通过主方法已经将System的字节码文件加载到类代码区,当调用时,会在堆区创建三个对象,
System.in,System.out,System.err,调用in的println()方法,当打印s的时候,s是复写了toString方法的,所有输出的是
"Hello World!"而不是
"Hello World!"的地址。
这样就简单的分析完了java虚拟机运行helloworld的过程。