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. 【转】JavaScript之web通信

    原文转自:http://cloudbbs.org/forum.php?mod=viewthread&tid=28773&page=1&extra=#pid180304 一.前言 ...

  2. 用HTML和CSS实现WWDC 2015上的动画效果

    用HTML和CSS实现WWDC 2015上的动画效果 动画效果WWDC 2015   原文:https://cssanimation.rocks/wwdc15/ 译者:周晓楷(@Helkyle) 每年 ...

  3. android 瀑布流效果 保存地址

    http://tech.ddvip.com/2013-09/1379785198203013_2.html

  4. REDIS 事务机制

    基本事务操作: 任何数据库都必须要保证一种原子执行操作:最基本的原子执行操作肯定是需要提供: 举一个例子来说明: 当对某个Key 做一个统计: 可能不同的Client做它那部分的统计,一段时间后,服务 ...

  5. 最新AFNetworking

    1.网络监测 /** * 网络检测 */ - (void)networkingMonitoring { //打开网络监测 [[AFNetworkReachabilityManager sharedMa ...

  6. 返回顶部demo

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  7. tableView优化性能

    在iOS应用中,UITableView应该是使用率最高的视图之一了.iPod.时钟.日历.备忘录.Mail.天气.照片.电话.短信. Safari.App Store.iTunes.Game Cent ...

  8. same story,different day

    多亏了这个重感冒,宏伟计划险些又断了. 我是说当然断了一天,但是比起鄙人过往的八千多个日子,喔,虚惊一场. 又看了段lietome,作为不会看眼色的人,这样的美剧太有吸引力了.想象一下,一个八分半美女 ...

  9. C#的循环语句

    1.输入月份,日期号,输出是见年的第几天. 循环语句: for 格式 for(初始条件;循环条件;状态改变) { 循环体,执行代码(break;跳出循环体) } 2.一个游戏,前20关是每一关自身的分 ...

  10. CGRectInset & CGRectOffset

    1.CGRectInset CGRect CGRectInset (   CGRect rect,   CGFloat dx,   CGFloat dy);以原rect为中心,再参考dx,dy,进行缩 ...