1、jvm内存分配
程序计数器:当前线程所执行的字节码文件的行号指示器
虚拟机栈:存储的方法出口,局部变量,每个线程都有自己的栈空间
本地方法栈:带有native的方法
方法区:线程共享,存储的常量、类信息,静态变量;
堆:内存中最大的,线程共享,对象实例化都在这里;
2、堆和栈的区别:
存储东西不同,堆存放的死对象实例化,栈存放的是方法出口
堆是线程共享的,而栈是线程私有的。
内存大小:栈的内存大小是编译期间就确定的,而堆因为物理空间分配不连续,所以实在运行时才确定,内存大小不确定,一般堆要大于栈
物理地址:堆物理内存分配是不连续的,栈因为数据结构采用的是栈,先进后出,所以物理分配空间是连续的
3、引用拷贝和对象拷贝 深拷贝和浅拷贝
引用拷贝:并不会生成一个新的对象只是把新增一个对象引用地址,两个地址仍然指向同一个对象
举例:user user1=new user
user2=user1 两个usr都指向同一个对象
对象拷贝:会生成新的对象,深拷贝和浅拷贝都属于对象拷贝
浅拷贝:会生成新的对象,但是如果对象中的属性有引用数据类型,那么该属性对应的对象是不是生成新的
深拷贝:同样会生成新的对象,和浅拷贝不同的是,如果属性中包含引用数据类型,深拷贝也会生成该属性的新对象
4、对象在堆中怎么分配的
首先,我们需要知道堆内存是分为新生代和老年代的,而新生代又分为伊甸园区和幸存者区。一个新的对象优先是分配在伊甸园区(eden),如果eden没有足够的空间,那么则进行一次minorGC,如果经过一次mgc能够存活下来,那么则进去幸存者区,虚拟机为每个对象都定义了年龄计数器,每次经过一次gc都会年龄加一,当年龄达到默认的15次后则可以进入老年代。
当然并不是所有的对象都直接在eden分配,假如你是大对象,比如长数组,则直接进入老年代,这是因为新生代的垃圾回收机制采用的复制算法,大对象会导致大量的内存拷贝
5、什么是空间分配担保,为什么要有
总所周知,mgc是发生在新生代的垃圾回收机制,但是因为幸存者区的空间其实比较小,假设mgc执行完毕之后,仍然有大量对象存活下来,导致幸存者区内存不够,这个时候就需要老年代来分配担保,把对象存入到老年代中,但是老年代的空间是否足够容纳这些对象呢,所以就需要我们的空间分配担保;
什么是空间分配担保,就是在我们执行mgc之前,首先要判断,老年代可用内存空间是否大于新生代所有对象所占用的总空间,如果大于那就代表此次mgc是安全的可以执行,但是如果小于那么则看HandlePromotionFailure(是否设置空间分配担保),是否为true,如果为true,那么则继续判断老年代可用空间是否大于历届晋升到老年代的对象的平均大小,如果大于则进行mgc,但是此次mgc仍然是有风险的,如果小于或者为flase则进行full gc
6、垃圾回**收机制**
1、复制算法:复制算法是发生在新生代的垃圾回收算法,是把内存一分为二,比如分为AB两部分,那么则把a所有对象转移到b,然后在清除a。这样做的优点是没有垃圾碎片,缺点是内存可用空间变小。
2、标记清除算法:标记所有无用对象,然后在清除,这样做的缺点就是会产生很多垃圾碎片,优点是实现简单
3、标记整理算法:标记所有有用对象,然后移到一端,然后清除端外的,这样做解决了垃圾碎片,但是效率仍然较低