JVM三大性能调优参数
-Xss:规定了每个线程虚拟机栈(堆栈)的大小;(一般256K足够了,影响Java线程的多少)
-Xms:堆的初始值;
-Xmx:堆能达到的最大值;(一般设置为何上面一个相同大小的值,防止heap不够用发生内存抖动)
内存分配策略
静态存储:编译时确定每个数据目标在运行时的存储空间需求;
栈式存储:数据区需求在编译时未知,运行时模块入口前确定;
堆式存储:编译时或运行时模块入口都无法确定,动态分配;
Java内存模型中栈与堆的联系
Java内存模型中的堆与栈的区别
- 管理方式:栈自动释放,堆需要GC;
- 空间大小:栈比堆小;(堆存的是对象数据,栈存的是指针)
- 碎片相关:栈产生的碎片远小于堆;
- 分配方式:栈支持静态和动态分配,而堆仅支持动态分配;
- 效率:栈的效率比堆高;(栈的灵活度较低,堆的灵活度较高,堆操作的复杂度要高)
元空间、堆,线程独占部分间的联系-内存角度
不同JDK版本之间的intern()方法的区别——JDK6 VS JDK6+
本质上就是后来改善版的 intern 方法把字符串存到了堆中,寻找的时候也会到堆中去寻找,原因是为了避免由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryError: PermGen;(元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。)
JDK6的例子
解析:首先我们用引号声明的常量(“a”)都会在字符串常量池中创建出来,而new出来的string对象(new String(“a”))都会在Java heap中创建出来,intern的时候会试图把"a"字符串的副本放进常量池,但是由于常量池已有"a",所以放不进去,所有s1和s2引用不同的地址;"aa"则是首先在Java heap中生成,然后 intern 把"aa"的副本放进常量池,成功放进去;所以s4和s3不同。
注:此处虽然都是false,但是常量池和Java heap中字符串的生成顺序不一样
JDK6+的例子
解析:解析:首先我们用引号声明的常量(“a”)都会在字符串常量池中创建出来,而new出来的string对象(new String(“a”))都会在Java heap中创建出来,intern的时候会试图把"a"字符串引用放进常量池,但是由于常量池已有"a",所以放不进去,所有s1和s2引用不同的地址;"aa"则是首先在Java heap中生成,然后 intern 把"aa"的引用放进常量池,成功放进去;所以s4和s3相同。
注:新版本的intern与旧版本不同的是:旧版本放进常量池的是字符串的副本,也就是字符串的内容;而新版本则是把字符串的引用放进常量池;所以当常量池不存在字符串的时候,新版本的 intern 之后的引用就和之前的一样