jvm学习心得
java中存储数据的几种区域
1首先是Pcregister
他存储的的线程运行的地址,每个线程会有一个
2然后是栈
他提供一个线程运行的场所,每一个线程都有一个栈,他存放局部变量,中间结果和返回值
3堆
他存放所有jvm的对象(其实不是所有,有时候对象也存放在栈上),每一个jvm只有一个堆
4方法区
他存放clss的相关信息,如常量池、字段和方法的数据、方法和构造器的代码
你是否认为所有的基本类型都放在栈上,所有的对象都放在堆上?答案是否定的
类是放在堆上的,而且类里面的基本类型还是放在堆上的,而基本类型的局部变量才是放在栈上的
方法在执行的时候会有一个压栈的过程,每个压入的东西就做frame,他保存了方法执行时的数据,当方法返回的时候(不管是正常返回还是异常返回),他都会弹出栈,如果有返回值,他会把返回值在压入栈中。一个方法不一定只有一个栈,如递归调用,执行一次方法就会push一个frame,return就pop,直到最后一frame被pop
大家可以做一个实验,有这样一个类
public class Load {
public static int a=5;
public static final int b=5;
public Load()
{
}
static
{
System.out.println("im loaded");
}
public static void main(String[] args) {
System.out.println(Load.a);//对象会被加载
System.out.println(Load.b);//对象是不会加载的
}
为什么呢
类加载有这样一条规则,当对象的一个静态方法或静态域被访问的时候,类就会被加载,所以即使构造方法没有加static,他还是一个静态方法,类加载后,静态方法会被放在静态区里,那为什么第二条不会被加载呢,因为在javac后,System.out.println(Load.b);会被编译System.out.println(5);所以他不会加载
jvm要学习的东西真的很多,但对于做业务的人来说真的不是很有用,但重要的是兴趣,做一辈子java开发,不知道他到底怎么实现的会不会有点悲哀,呵呵
最后说明两个关键字
transient
当你的一个对象或字段申明为这个的时候,但序列化时,他将不被序列化,所以平时我们所说的没有加这个字段的单例不能算是真正的单例,因为序列化再反序列化,就会存在连个对象,所以要加transient
native
本地方法,我学习hashcode方法的时候有个疑问,当一个类没有覆盖hashcode方法时,他会调用父类的hashcode方法,也就是object的hashcode方法
,但object的hashcode方法没有任何方法体,但他确实返回了一个值,
public native int hashCode();
但他申明了native后,这个方法由更底层的语言去实现,如C或C++,我是这样理解的,这个方法就好像一个接口,然后由其他更底层的语言来实现这个方法
欢迎大家指正错误