一、JVM三大性能调优参数-Xms -Xmx -Xss的含义
-Xss:规定了每个线程虚拟机栈(堆栈)的大小(一般情况下256k就足够了)此配置会影响进程中并发线程数的大小;
-Xms:堆的初始值即该进程创建出来时初始堆的大小,如果对象容量超过了初始值大小,会自动扩容,扩容的最大值就是-Xmx设置的值;
-Xmx:堆能达到的最大值;
一般情况下我们会将-Xms和-Xmx设置成一样大小,因为当Heap不够用,发生扩容时,会发生内存抖动,影响程序运行时的稳定性;
二、Java内存模型中堆和栈的区别
想要讲清楚区别,首先要先了解程序运行时的内存分配策略,总共有以下三种:
静态存储:编译时确定每个数据目标在运行时的存储空间需求,所以程序中不能存在可变数据型结构,也不允许有嵌套或递归的数据型结构出现,因为他们会导致编译程序时无法计算出存储空间;
栈式存储:数据取需求在编译时未知,运行时模块入口前确定,所以必须在运行时知道该模块的空间需求,才能分配内存,同样也是先进后出;
堆式存储:编译时或运行时模块入口都无法确定,动态分配;
接着再来了解一下堆和栈之间的联系:
我们知道创建好的对象实例或数组都放在堆中,想要使用堆中的对象实例或数组就需要在栈中定义一个变量,这个变量的取值就是想要使用的对象实例或数在堆中的首地址(也就是C语言中的指针),这样就能使用栈中的变量来使用堆中的对象实例或数组,当方法执行完时,栈中的变量就会被删除,而堆中的对象实例或数组是不会被删除的,只有当对象实例或数组没有被任何栈中变量引用时,才会被认为是垃圾,这时会由GC来将其回收,下图可以清晰的描述出栈是如何引用对中的数据:
所以在了解了联系之后,我们就能够总结出堆和栈两者的区别了,可以分为以下几种方式:
管理方式:栈自动释放,堆需要GC;
空间大小:栈比堆小;
碎片相关:栈产生的碎片远小于堆;
分配方式:栈支持静态和动态分配,而堆仅支持动态分配;
效率:栈的效率比堆高,但是堆的灵活性比栈好,有得必有失;
三、元空间、堆、线程独占部分间的联系-内存角度
下图为一段非常简单的代码:
当要执行该程序时,其中的变量都分别存储在什么位置呢?请看下图你就知道了:
类相关的信息都存在在了元空间中,包括System;
HelloWorld对象实例和name的对象实例都存在了堆中;
线程独占(也就是计数器和栈)存储了当前执行的行数,和对堆中两个对象实例引用的首地址;
四、不同JDK版本之间的intern()方法的区别——JDK6 VS JDK6+
String s = new String("a");
s.intern();
JDK6:当调用intern方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,将此字符串对象添加到常量池中,并且返回该字符串对象的引用。
JDK6+:当调用intern方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,如果该字符串对象已经存在于Java堆中,则将堆中对此对象的引用添加到字符串常量池中,并且返回该引用;如果堆中不存在,则在池中创建该字符串并返回其引用。