-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
291 lines (201 loc) · 15.4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Thinking & Acting</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta property="og:type" content="website">
<meta property="og:title" content="Thinking & Acting">
<meta property="og:url" content="https://jwnie.github.io/index.html">
<meta property="og:site_name" content="Thinking & Acting">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Thinking & Acting">
<link rel="alternate" href="/atom.xml" title="Thinking & Acting" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">Thinking & Acting</a>
</h1>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="搜索"></a>
</nav>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" results="0" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="https://jwnie.github.io"></form>
</div>
</div>
</div>
</header>
<div class="outer">
<section id="main">
<article id="post-JVM笔记-内存区域" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2017/01/08/JVM笔记-内存区域/" class="article-date">
<time datetime="2017-01-08T04:54:00.000Z" itemprop="datePublished">2017-01-08</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/分类/Java/">Java</a>►<a class="article-category-link" href="/分类/Java/JVM/">JVM</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/01/08/JVM笔记-内存区域/">JVM读书笔记系列-自动内存管理机制</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>摘要: JVM内存的划分,导致内存溢出异常的可能区域。</p>
<h1 id="1-JVM运行时内存区域"><a href="#1-JVM运行时内存区域" class="headerlink" title="1. JVM运行时内存区域"></a>1. JVM运行时内存区域</h1><p>JVM在执行Java程序的过程中会把它所管理的内存划分为以下几个区域:</p>
<p><img src="/img/JVM-HotSpot-RunningDataArea.jpg" alt="图1 JVM运行时数据区" title="图片来源于网络" width="50%" height="40%"> </p>
<h2 id="1-1-程序计数器"><a href="#1-1-程序计数器" class="headerlink" title="1.1 程序计数器"></a>1.1 程序计数器</h2><p> 程序计数器是一块较小的内存空间,在Java虚拟机规范中是唯一一个未规定OutOfMemoryError的内存区域。<br> 程序计数器可看作当前线程所执行字节码的行号指示器。字节码解释器工作时通过改变计数器的值来选取下一条待执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器来完成。<br> 每个线程均有一个独立的程序计数器。若线程执行的是一个Java方法,计数器记录的值是正在执行虚拟机字节码地址;若执行的是Native方法,计数器值为空(Undefined)。</p>
<h2 id="1-2-Java虚拟机栈"><a href="#1-2-Java虚拟机栈" class="headerlink" title="1.2 Java虚拟机栈"></a>1.2 Java虚拟机栈</h2><p>Java虚拟机栈也就是我们经常说的”栈”(其实这个说法不够严谨<^_^>),它是线程私有的,生命周期与线程相同。<br>虚拟机栈描述的是Java方法执行的内存模型:每个方法执行时都会创建一个栈帧,用于存储局部变量栈、操作数栈、动态链接、方法出口等信息。每个方法从调用到执行完成的过程,都对应者一个栈帧在虚拟机栈中入栈到出栈的过程。<br>局部变量表存放了编译期可知的8种基本数据类型、对象引用(reference类型,指向对象起始地址的引用指针或代表对象的句柄或其他与此对象相关的位置)、returnAddress类型(指向一条字节码指令的地址)。<br>Java虚拟机规范对这块区域规定了两种异常情况: </p>
<ul>
<li>StackOverflowError<br>线程请求的栈深度大于虚拟机所允许的深度,将抛出此异常;</li>
<li>OutOfMemoryError<br>若虚拟机栈可以动态扩展,但在扩展时无法申请到足够的内存,将抛出此异常;</li>
</ul>
<h2 id="1-3-本地方法栈"><a href="#1-3-本地方法栈" class="headerlink" title="1.3 本地方法栈"></a>1.3 本地方法栈</h2><p>与虚拟机栈类似,但它执行的Native方法服务。</p>
<h2 id="1-4-Java堆"><a href="#1-4-Java堆" class="headerlink" title="1.4 Java堆"></a>1.4 Java堆</h2><p>“GC”堆,虚拟机启动时创建,为所有线程共享的一块区域。在Java虚拟机规范描述中,所有对象实例和数组都要在堆上分配(随着JIT编译器的发展和逃逸技术的逐渐成熟,所有对象在堆上分配也变得不是这么绝对)。<br>如果堆中剩余内存不足以完成实例的分配,且无法再扩展,将抛出OutOfMemoryError。</p>
<h2 id="1-5-方法区"><a href="#1-5-方法区" class="headerlink" title="1.5 方法区"></a>1.5 方法区</h2><p>“Non-Heap”,存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码等数据。<br>根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError。</p>
<h2 id="1-6-运行时常量池"><a href="#1-6-运行时常量池" class="headerlink" title="1.6 运行时常量池"></a>1.6 运行时常量池</h2><p>方法区的一部分,在类加载后进入方法区时,存放编译期生成的各种字面量和符号引用。<br>在运行期间,也可能将新的常量放入池中,如String常用的intern()方法。<br>当无法满足内存分配需求时,将抛出OutOfMemoryError。</p>
<h2 id="1-7-直接内存"><a href="#1-7-直接内存" class="headerlink" title="1.7 直接内存"></a>1.7 直接内存</h2><p>这部分区域并不是虚拟机运行时数据区的一部分,也非Java虚拟机规范中定义的内存区域,但也被频繁使用,亦可能抛出OutOfMemoryError。<br>直接内存主要为NIO(JDK1.4 加入的类)使用,通过存储在Java堆中的DirectByteBuffer对象对这块内存的引用进行操作。在某些场合能显著提高性能,避免了Java堆和Native堆中来回复制数据。</p>
<h1 id="2-HotSpot虚拟机对象"><a href="#2-HotSpot虚拟机对象" class="headerlink" title="2. HotSpot虚拟机对象"></a>2. HotSpot虚拟机对象</h1><p>讨论Java堆中普通对象分配、布局和访问的过程。</p>
<h2 id="2-1-对象的创建"><a href="#2-1-对象的创建" class="headerlink" title="2.1 对象的创建"></a>2.1 对象的创建</h2><ul>
<li><p>虚拟机遇到一条new命令时,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载、解析和初始化过,若没有,则先执行相应的类加载过程;</p>
</li>
<li><p>在类加载检查通过后,虚拟机将为新生对象分配内存:</p>
<ul>
<li>指针碰撞<br>若Java堆中的内存是绝对规整的,所有用过的和空闲的内存都各放一边,中间放着一个指针作为分界点的指示器,那分配内存仅仅是将指针向空闲空间方向移动一段与对象大小相等的距离;</li>
<li>空闲列表<br>Java堆中的内存并不规整,此时虚拟机必须维护一个列表,记录哪些内存块是可用的,在分配的时候从列表上找到一块足够大的空间划分给对象实例,并更新列表上的记录。</li>
</ul>
</li>
</ul>
<p>并发情况下,在堆上分配内存,可能出现内存分配的同步问题,解决方案有两个,一个就是同步内存(CAS)分配动作;另一个就是采用TLAB(本地线程分配缓冲),即在Java堆中针对每个线程先预先分配一小块内存。这样当线程需要分配内存时就在自己的TLAB上进行,从而避免同步的开销。但是当TLAB分配满重新分配TLAB时仍需要同步。在内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)。</p>
<ul>
<li>虚拟机将要对对象进行必要的设置,如这个对象是哪个类的实例,如何找到类的元数据信息、对象的hashCode和GC分代年龄等信息。这些信息存放在对象的对象头中。</li>
</ul>
<p>最后执行init方法,从而产生真正可用的对象。</p>
<h2 id="2-2-对象的内存布局"><a href="#2-2-对象的内存布局" class="headerlink" title="2.2 对象的内存布局"></a>2.2 对象的内存布局</h2><p>在HotSpot虚拟机中,对象在内存的存储的布局可分为3块区域:对象头、实例数据、对齐填充。</p>
<ul>
<li><p>对象头</p>
<ul>
<li>Mark Word<br>存储对象自身的运行时数据,如hashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等;</li>
<li>类型指针<br>对象指向它的类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例。</li>
</ul>
</li>
<li><p>实例数据<br>程序代码中所定义的各种类型的字段内容,包括从父类继承下来的。</p>
</li>
<li>对齐填充<br>并不是必然存在,仅仅起着占位符作用,以满足HotSpot VM 自动内存管理系统对对象起始地址必须是8字节的整数倍要求。</li>
</ul>
<h2 id="2-3-对象的访问定位"><a href="#2-3-对象的访问定位" class="headerlink" title="2.3 对象的访问定位"></a>2.3 对象的访问定位</h2><p>Java程序通过栈上的reference数据来操作堆上的具体对象。主流的访问方式:</p>
<ul>
<li><p>句柄<br>Java堆中将划分一块内存用作句柄池,reference中存储的就是对象的句柄地址,而句柄包含了对象实例数据与类型数据各自的具体地址信息。<br>优点:当对象移动时,只需要改变句柄的指针即可,而相应的reference则不需要做变动;<br><img src="/img/HandleAccess.jpg" title="图片来源于网络"> </p>
</li>
<li><p>直接指针<br>reference存储的是对象地址,通过reference就能访问数据。<br>优点:访问速度快,相对句柄的方式而言少了一次指针定位的开销。HotSpot VM使用的是此种方式。<br><img src="/img/PointAccess.jpg" title="图片来源于网络"> </p>
</li>
</ul>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><p> <a href="http://product.dangdang.com/23259731.html" target="_blank" rel="external">深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)</a></p>
</div>
<footer class="article-footer">
<a data-url="https://jwnie.github.io/2017/01/08/JVM笔记-内存区域/" data-id="cixofdbxh0001i0r8zs2ezi9f" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/标签/JVM/">JVM</a></li></ul>
</footer>
</div>
</article>
<article id="post-Good Night" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/12/17/Good Night/" class="article-date">
<time datetime="2016-12-17T15:36:06.000Z" itemprop="datePublished">2016-12-17</time>
</a>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/12/17/Good Night/">Good Night</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>摘要:<br>正文: Just builded the blog success by using git and hexo. lol~~</p>
</div>
<footer class="article-footer">
<a data-url="https://jwnie.github.io/2016/12/17/Good Night/" data-id="cixofdbxd0000i0r8t8h4dtbe" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/标签/日常/">日常</a></li></ul>
</footer>
</div>
</article>
</section>
<aside id="sidebar">
<div class="widget-wrap">
<h3 class="widget-title">分类</h3>
<div class="widget">
<ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/分类/Java/">Java</a><ul class="category-list-child"><li class="category-list-item"><a class="category-list-link" href="/分类/Java/JVM/">JVM</a></li></ul></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">标签</h3>
<div class="widget">
<ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/标签/JVM/">JVM</a></li><li class="tag-list-item"><a class="tag-list-link" href="/标签/日常/">日常</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">标签云</h3>
<div class="widget tagcloud">
<a href="/标签/JVM/" style="font-size: 10px;">JVM</a> <a href="/标签/日常/" style="font-size: 10px;">日常</a>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">归档</h3>
<div class="widget">
<ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/归档/2017/01/">一月 2017</a></li><li class="archive-list-item"><a class="archive-list-link" href="/归档/2016/12/">十二月 2016</a></li></ul>
</div>
</div>
<div class="widget-wrap">
<h3 class="widget-title">最新文章</h3>
<div class="widget">
<ul>
<li>
<a href="/2017/01/08/JVM笔记-内存区域/">JVM读书笔记系列-自动内存管理机制</a>
</li>
<li>
<a href="/2016/12/17/Good Night/">Good Night</a>
</li>
</ul>
</div>
</div>
</aside>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info" class="inner">
© 2017 Jwnie<br>
Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
</div>
</div>
</footer>
</div>
<nav id="mobile-nav">
<a href="/" class="mobile-nav-link">Home</a>
<a href="/archives" class="mobile-nav-link">Archives</a>
</nav>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script src="/js/script.js"></script>
</div>
</body>
</html>