求你了,别再说Java对象都是在堆内存上分配空间的了!
△Hollis, 一个对Coding有着独特追求的人△
Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点,所以,即使是一个Java的初学者,也一定或多或少的对JVM有一些了解。可以说,关于JVM的相关知识,基本是每个Java开发者必学的知识点,也是面试的时候必考的知识点。
在JVM的内存结构中,比较常见的两个区域就是堆内存和栈内存(如无特指,本文提到的栈均指的是虚拟机栈),关于堆和栈的区别,很多开发者也是如数家珍,有很多书籍,或者网上的文章大概都是这样介绍的:
1、堆是线程共享的内存区域,栈是线程独享的内存区域。2、堆中主要存放对象实例,栈中主要存放各种基本数据类型、对象的引用。
但是,作者可以很负责任的告诉大家,以上两个结论均不是完全正确的。
在我之前的文章《Java堆内存是线程共享的!面试官:你确定吗?》中,介绍过了关于堆内存并不是完完全全的线程共享有关的知识点,本文就第二个话题来探讨一下。
对象内存分配
在《Java虚拟机规范》中,关于堆有这样的描述:
在Java虚拟机中,堆是可供各个线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。
在《Java堆内存是线程共享的!面试官:你确定吗?》文章中,我们也介绍过,一个Java对象在堆上分配的时候,主要是在Eden区上,如果启动了TLAB的话会优先在TLAB上分配,少数情况下也可能会直接分配在老年代中,分配规则并不是百分之百固定的,这取决于当前使用的是哪一种垃圾收集器,还有虚拟机中与内存有关的参数的设置。
但是一般情况下是遵循以下原则的:
对象优先在Eden区分配 优先在Eden分配,如果Eden没有足够空间,会触发一次Monitor GC 大对象直接进入老年代 需要大量连续内存空间的Java对象,当对象需要的内存大于-XX:PretenureSizeThreshold参数的值时,对象会直接在老年代分配内存。
JIT 技术
热点检测
基于计数器的热点探测(Counter Based Hot Spot Detection)。采用这种方法的虚拟机会为每个方法,甚至是代码块建立计数器,统计方法的执行次数,某个方法超过阀值就认为是热点方法,触发JIT编译。
编译优化
逃逸分析
public
staticString craeteStringBuffer(
String s1,
String s2) {
StringBuffer
sb =
newStringBuffer();
sb.append(s1);
sb.append(s2);
return
sb.toString();
}
同步省略 标量替换 栈上分配
标量替换、栈上分配
标量替换
{
alloc();
}
privatestaticvoidalloc()
{
Point point =
new Point(
1,
2);
System.
out.println(
"point.x="+point.x+
"; point.y="+point.y);
}
classPoint
{
privateint
x;
privateint
y;
}
{
int
x =
1;
int
y =
2;
System.
out.println(
"point.x="+x+
"; point.y="+y);
}
实验证明
{
long
a1 = System.currentTimeMillis();
for
(
int i =
0; i <
1000000; i++) {
alloc();
}
// 查看执行时间
long
a2 = System.currentTimeMillis();
System.
out.println(
"cost " + (a2 - a1) +
" ms");
// 为了方便查看堆内存中对象个数,线程sleep
try
{
Thread.sleep(
100000);
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
}
privatestaticvoidalloc()
{
User user =
new User();
}
staticclassUser
{
}
➜ ~ jmap -histo
2809 num
#instances #bytes class name----------------------------------------------
1
:
52487282184 [I
2
:
100000016000000 StackAllocTest$User
3
:
68062093136 [B
4
:
80061320872 [C
5
:
4188100512 java.lang.
String6
:
58166304 java.lang.
Class num
#instances #bytes class name----------------------------------------------
1
:
524101944280 [I
2
:
68062093136 [B
3
:
836191337904 StackAllocTest$User
4
:
80061320872 [C
5
:
4188100512 java.lang.
String6
:
58166304 java.lang.
Class逃逸分析并不成熟
总结
推荐阅读:
好文章,我 在看
最新评论
推荐文章
作者最新文章
你可能感兴趣的文章
Copyright Disclaimer: The copyright of contents (including texts, images, videos and audios) posted above belong to the User who shared or the third-party website which the User shared from. If you found your copyright have been infringed, please send a DMCA takedown notice to [email protected]. For more detail of the source, please click on the button "Read Original Post" below. For other communications, please send to [email protected].
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。