java中的堆内存和栈内存分别存放什么东西?

栈内存:存放基本类型的变量和对象的引用变量
堆内存:存放new创建的对象和数组。
注意:
1.Java中每一个线程都有一个栈区,每一个栈中的元素都是私有的,不被其他栈所访问。
2.Java中只有一个堆,被所有线程共享。

Java内存模型:

图片说明
1.每个线程都有独立的栈空间。
2.所有线程都访问同一个堆空间。
3.操作系统中的CPU从寄存器中取数据,寄存器不直接从主内存中获取数据,而是先把主内存的数据读到缓存(缓存也分一级缓存和二级缓存)里面,再将缓存的数据读取到寄存器里面。
4.JVM中的共享数据有可能被分配在寄存器中,每个CPU都有自己的寄存器,一个CPU不能读取其他CPU上寄存器中的内容。所以如果两个线程在不同的CPU上,而共享数据分配在不同的寄存器中,对贡献数据的更新另一个CPU不会读取到更新后的。就会产生可见性问题。
5.如果共享数据分配在主内存中,也不能保证数据的可见性。因为CPU不直接对主内存进行访问,而是通过高速缓存进行的。一个处理器上运行的线程对数据的更新可能只是更新的写缓冲器中,还没到达缓存区中,更不用说主内存与缓存做同步了。另一个处理器读不到其他写缓冲器的数据,所以另一个处理器是获取不到更新的数据,就会产生可见性问题。
6.一个处理器的缓存是不能读取其他处理器的缓存,但可以通过缓存一致性协议来读取其他处理器上的缓存并更新,这个过程就称为缓存同步。这样处理器也能访问到其他处理器的缓存了,即能访问到对共享数据的更新。保障线程的可见性。一个共享数据的最终更新写入处理器的缓冲区中,不再停留在写缓存器中,这个过程称为冲刷处理器缓存。

可以将Java内存模型抽象为:

图片说明
图片说明
共享数据存储在主内存中,每个线程在自己的工作内存中保存一个副本,所以线程操作数据是保存工作内存中的副本,不是直接操作主内存的共享数据。线程对工作内存的数据进行操作其他线程是看不见的。所以就会有可见性问题。