1.对象的创建
虚拟机遇到一条new指令时,首先会去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,则必须先进行相应的类的加载。

2、对象的访问定位
简历对象是为了使用对象,我们的java程序需要通过栈上的refrerence数据来操作堆上的具体对象。由于reference类型在java虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用应该通过何种方式去定位、访问堆中的对象的具体位置,所以对象访问方式也是取决于虚拟机实现而定的。目前主流的访问方式有使用句柄和直接指针两种。

使用句柄:那么 java堆中会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。

使用直接指针:那么Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址。

  使用句柄来访问的最大好处就是refernce中存储的是稳定的句柄地址,在对象被移动时,将会改变句柄中的实例数据指针,而reference本身不需要修改。

  使用直接指针访问方式的最大好处就是速度更快,它节省了一次指针定位的时间开销,由于对象的访问在JAVA中非常频繁,因此这类开销积少成多后也是一项非常可观的执行成本。

3、JAVA堆溢出

  JAVA堆用于存储对象实例,不断地创建对象,并保证GC, Root到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常。  

  下面设置运行参数为 -Xms521M -Xmx512M -XX:+HeapDumpOnOutOfMemoryError,让虚拟机出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析。

package JVMtest;

import java.util.ArrayList;
import java.util.List; public class HeapOOM {
static class OOMObject{ } public static void main(String[] args){
List<OOMObject> list = new ArrayList<OOMObject>();
while(true){
list.add(new OOMObject());
}
}
}

  将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展

4、虚拟机栈和本地方法栈溢出

  栈容量只由-Xss参数设定。关于虚拟机栈和本地方法栈,在JAVA虚拟机规范中描述了两种异常:

  (1)如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。

  (2)如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

  测试时,通过不断地创建线程的方式倒是可以产生内存溢出异常,但这样产生的内存溢出异常与栈空间是否足够大并不存在任何联系,或者再准确的说,在这种情况下,为每个线程的栈分配的内存越大,反而越容易产生内存溢出的异常。原因是,操作系统分配给每个进程的内存是有限制的,譬如32为的Windows限制为2GB,虚拟机提供了参数来控制JAVA堆和方法去的两部分最大的内存值。那么剩下的内存为,操作系统限制的2GB-Xms(最大堆容量)-MaxPermSize(最大方法区容量),程序计数器消耗内存很小,可以忽略。如果虚拟机本身消耗的内存不计算在内,剩下的内存就由虚拟机和本地方法栈瓜分了。每个线程分配到的栈容量越大,可以建立的线程数量自然就减少,建立线程时,就很容易把剩下的内存耗尽。

package JVMtest;

public class JavaVMStackOOM {
private void dontStop(){
while(true){ }
} public void stackLeankByThread(){
while(true){
Thread thread = new Thread(new Runnable(){ @Override
public void run() {
dontStop();
}
});
thread.start();
}
} public static void main(String args[]){
JavaVMStackOOM oom = new JavaVMStackOOM();
oom.stackLeankByThread();
}
}

5、方法区和运行时异常量池溢出

  比如String.intern()是一个Native方法,作用是,如果字符串常量池中已经包含一个等于此String对象的字符串,则返回带包翅中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。

  方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。这些区域的测试,基恩的思路是运行时产生大量的类去填满方法区,直到溢出。

  

package JVMtest;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; public class JavaMethodAreaOOM {
public static void main(String args[]){
while(true){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor(){ @Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj,args);
} });
enhancer.create();
}
}
static class OOMObject{ }
}

HotSpot 自动内存管理笔记与实战的更多相关文章

  1. JVM自动内存管理学习笔记

    对于使用 C.C++ 的程序员来说,在内存管理领域,他们既是拥有最高权力的皇帝又是从事最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任.对于 Java 程 ...

  2. [深入理解Java虚拟机]<自动内存管理>

    Overview 走近Java:介绍Java发展史 第二部分:自动内存管理机制 程序员把内存控制的权利交给了Java虚拟机,从而可以在编码时享受自动内存管理.但另一方面一旦出现内存泄漏和溢出等问题,就 ...

  3. JVM自动内存管理机制--读这篇就GO了

    之前看过JVM的相关知识,当时没有留下任何学习成果物,有些遗憾.这次重新复习了下,并通过博客来做下笔记(只能记录一部分,因为写博客真的很花时间),也给其他同行一些知识分享. Java自动内存管理机制包 ...

  4. 深入理解Java虚拟机(自动内存管理机制)

    文章首发于公众号:BaronTalk 书籍真的是常读常新,古人说「书读百遍其义自见」还是很有道理的.周志明老师的这本<深入理解 Java 虚拟机>我细读了不下三遍,每一次阅读都有新的收获, ...

  5. JVM | 第1部分:自动内存管理与性能调优《深入理解 Java 虚拟机》

    目录 前言 1. 自动内存管理 1.1 JVM运行时数据区 1.2 Java 内存结构 1.3 HotSpot 虚拟机创建对象 1.4 HotSpot 虚拟机的对象内存布局 1.5 访问对象 2. 垃 ...

  6. JVM自动内存管理-Java内存区域与内存溢出异常

    摘要: JVM内存的划分,导致内存溢出异常的可能区域. 1. JVM运行时内存区域 JVM在执行Java程序的过程中会把它所管理的内存划分为以下几个区域: 1.1 程序计数器 程序计数器是一块较小的内 ...

  7. JVM介绍&自动内存管理机制

    1.介绍JVM(Java Virtual Machine,Java虚拟机) JVM是Java Virtual Machine的缩写,通常成为java虚拟机,作为Java可以进行一次编写,到处执行(Wr ...

  8. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

  9. JVM自动内存管理机制——Java内存区域(上)

    一.JVM运行时数据区域概述 Java相比较于C/C++的一个特点就是,在虚拟机自动内存管理机制的帮助下,我们不需要为每一个操作都写像C/C++一样的delete/free代码,所以也不容易出现内存泄 ...

随机推荐

  1. zenefits oa - random(5) to generate a random(7)

    If given a function that generates a random number from 1 to 5, how do you use this function to gene ...

  2. SDK截图(三):压缩位图之理论准备篇

    压缩位图我们使用简单的行程长度编码的方法,详情参考<windows程序设计>15章之DIB压缩. 在BITMAPINFOHEADER结构中有两个和位图压缩有关的字段,分别是biCompre ...

  3. Mac、Linux更换命令行svn diff为P4Merge、vimdiff

    2015-01-21 21:25:52 这里先把那个程序员大神的博客地址贴一下(PS:大神,我不是为了抄袭哦,真是怕自己忘记了),http://www.ccvita.com/445.html,里面还有 ...

  4. JUCE 界面库显示中文乱码问题

    JUCE 界面库显示中文乱码问题 环境: Windows7 64位 旗舰版 Visual Studio Ultimate 2012 JUCE 4.1 问题描述: 直接使用juce::String存储中 ...

  5. Tomcat笔记

    总体架构: 由三部分组成:Service.Connector.Container 多个Connector对应一个Container,构成一个Service 为Service提供一个生存环境 如何处理多 ...

  6. 打造IE6的position:fixed整理篇

    fixed真的是一个很好的属性.特别是做弹层的时候.可惜的是“国内主流浏览器”IE6大大不支持. 一般的我们都会通过CSS中的表达式来解决这个问题. .fixed { position:absolut ...

  7. codeforces 733D

    明白了自己这么菜的原因多半是赛后不肯去补那些需要多花点时间思考的题目以及效率不高,但愿现在还不算晚... #include<bits/stdc++.h> #include<iostr ...

  8. Apache-Jemeter web性能测试工具使用

    Jmeter是一款java开源的性能测试软件. 要使用该工具进行性能测试,首先需要下载该工具到你的电脑,接着配置java开发环境以及Jmeter环境.搭建完成之后,OK,我们就可以进行测试了. 测试第 ...

  9. Could not load type from string value 'DALMSSQL.DBSessionFactory,DALMSSQL'.

    问题: 原因: DAL.dll不在程序目录下        --调了老半天.

  10. Qt开发中的实用笔记二--中文转码问题和string转换问题:

    一,中文乱码转码问题 1,转码三句话:window下默认是GBK格式,linux下默认是UTF-8,看情况转换UTF-8/GBK QTextCodec::setCodecForTr(QTextCode ...