看了很多jvm写的文章,网上都是一转再转,讲的也不细,对于实际出现的问题用他们的原理来讲很难讲通,今天我特地自己理了一下,帮助别人的同时也提高自己,希望有不组的地方多指点
jvm研究
为什么要研究:首先研究这个可以让我们更加清楚jvm的工作原理,和解决实际生产中堆溢出和栈溢出的原因,同时对为什么会产生同步问题也有了更进一步的思考
首先jvm会有一个classload机制加载你所有的类和一些本地方法等,这个我就不再重复讲,主要讲下面一块
jvm对数据的存储
jvm对数据存储分5大块:
1.堆
2.栈
3.方法区(方法区(主要2个):常量池,静态成员区)
4.本地方法栈
5.程序计数器
首先,除了栈不是线程共享之外,其他都是线程共享
堆中存放的数据:数组和任何new 的对象(连带着对象的成员变量是属于每个对象的,所以也是放在堆中。例子:单例模式中,对一个成员变量操作会有同步问题。备注:servlet的机制)。 方法中new的对象一样存放在堆中,所以当你在一个方法中new很多对象,一样会出现堆溢出。
栈中存放的东西:(这里主要讲一个线程的流程)准确来说栈是给线程执行的一个通道,每个线程在启动进入栈时,jvm都会赋予一个栈帧给这个线程,栈帧中存放(中间结果集,方法中变量,对象的引用等。因为每个线程都有一个栈帧,所以方法内部变量都是线程安全的。所说的栈是线程安全的也是这个原因。所以很多文章说基本类型int是放在栈中,但是我觉得这个不太准确),在赋予栈帧的之后,jvm会从栈中给这个线程分配栈空间,假设线程使用a,b,c方法,那么线程就会把方法区中的方法放入栈中,然后通过栈帧来进行结果集的计算。所以当你的递归方法很多不能及时释放栈空间,就会有栈溢出。
本地方法:(static和final 修饰符的存放地方)
常量池:存放final的常量
静态成员区:存放类的成员变量(由于方法区是多线程共享,所以静态成员变量是具有同步问题的)
其他:存放方法的信息,比如方法名,方法返回值等等
程序计数器,本地方发栈,一个是线程的执行过程,一个是jvm自身的方法存放位置