您的位置  > 互联网

垃圾回收器的数据大小和生命周期是可以确定的

栈中数据的大小和生命周期是可以确定的。 当没有对数据的引用时,数据就会消失。 堆中的对象由垃圾收集器回收,因此不需要确定大小和生命周期,有很大的灵活性。

对于字符串:对其对象的引用存储在堆栈中。 如果它们是在编译期间创建的(直接用双引号定义),则它们存储在常量池中。 如果它们是在运行时创建的(新的),则只能确定它们。 存储在堆中。 对于相等的字符串,常量池中总是只有一份,堆中可能有多份。

s1 = "中国";

s2 =“中国”;

s3 = "中国";

ss1 = new (“中国”);

ss2 = new (“中国”);

ss3 = new (“中国”);

通过new生成字符串(假设为“china”)时,会先去常量池查找是否已经存在“china”对象。 如果没有,则在常量池中创建一个字符串对象,然后将其添加到堆中。 在常量池中创建这个“china”对象的副本。 这也是一道面试题:s = new("xyz"); 生成了多少个对象? 一两个,如果常量池中没有“xyz”,就是二。

成员变量和局部变量:

——成员变量是在方法外部、类内部定义的变量;

- 局部变量是在方法或语句块内定义的变量。 局部变量必须初始化。

形参是局部变量,局部变量的数据存在于栈内存中。 当方法消失时,栈内存中的局部变量也随之消失。

成员变量存储在堆中的对象中,并由垃圾收集器回收。

班级 {

国际日;

整月;

整数年;

(int d, int m, int y) {

天=d;

月=米;

年 = y;

类测试{

无效主(参数[]){

整数日期 = 9;

测试测试 = new Test();

测试。(日期);

d1=新(7,7,1970);

无效(整数我){

我 = 1234;

对于上面的代码,date是局部变量,i、d、m、y都是作为局部变量的形参,day、month、year是成员变量。 我们来分析一下代码执行时的变化:

main方法开始执行:int date = 9;

日期局部变量、基础类型、引用和值都存储在堆栈中。

测试测试 = new Test();

test是一个对象引用,存放在栈中,对象(new Test())存放在堆中。

测试。(日期);

i 是局部变量,引用和值都存储在堆栈中。 当方法执行完成后,i就会从栈中消失。

d1=新(7,7,1970);

d1是对象引用,存放在栈中,而对象(new())存放在堆中。 d、m、y是存储在栈中的局部变量,它们的类型都是基本类型,所以它们的数据也存储在栈中。 。 日、月、年是成员变量,它们存储在堆中(new()内部)。 当构造函数执行时,d、m、y将从堆栈中消失。

5、main方法执行完毕后,date变量、test、d1引用将从栈中消失,new Test()和new()将等待垃圾回收。

Java8元空间

方法区也是所有线程共享的。 主要用来存储类信息、常量池、方法数据、方法代码等。

方法区是JVM规范,永久代(空间)是这个规范的实现。

在JDK 1.8中,不再有“空格”间隔,取而代之的是(元空间)。

元空间的本质与永久代类似。 它们都是JVM规范中方法区的实现。 不过,元空间和永久代最大的区别在于,元空间不在虚拟机中,而是使用本地内存。 因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数指定元空间的大小:

-XX:初始空间大小。 当达到该值时,将触发垃圾收集以进行类型卸载。 同时GC会调整该值:如果释放大量空间,则适当减小该值; 如果释放了少量空间,则如果没有超出,则适当增加该值。

-XX:最大空间,默认没有限制。

除了上面两个指定大小的选项之外,还有两个与 GC 相关的属性:

-XX:oGC后剩余空间容量的最小百分比,减少为分配空间引起的垃圾回收

-XX:oGC后最大剩余空间容量的百分比,减少为释放空间引起的垃圾回收