- 浏览: 376540 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
surpassno:
很不错,学习了
一个对象占用多少字节? -
ysyzww:
你这么牛逼,你父母知道吗
maven使用技巧 -
妖人不要跑:
JDK中反序列化对象的过程(ObjectInputStream#readObject) -
lanhz:
谢楼主,构建成功了
Mac OSX 10.9 上build openjdk8和openjdk7 -
zqb666kkk:
通过了吗 ?????
淘宝北京专场java面试题(2011-12-31)
一、概述
运行时数据区是jvm运行时的内存布局,类装载到内存后存放的位置,为执行引擎提供所需指令和数据。运行时数据区包括:堆、栈、方法区、本地方法栈、pc计数器。
接下来会详细介绍各个部分,并介绍直接内存访问和方法区中的常量池,另外对于每个区域可能发生的内存异常用demo做讲解。
二、详细介绍各部分
1、堆
分配运行时产生的对象分配在堆中,但是并不是一定就分配在堆中,随着运行时编译器优化技术的不断进步,逃逸分析和标量替换技术的不断成熟,对象也可以分配到栈中。由于jvm内存是由虚拟机自己分配和回收,不需要开发人员手工干预,所以jvm一般会提供gc功能,但是jvm spec并没有明确要求必须提供。
整个系统只有一个堆,所有的对象分配都在一个逻辑区域。堆是一个多线程共享的区域,所以对堆中对象的访问就需要考虑并发。(jvm有什么措施)。
在jvm的实现中,一般堆都会划分成不同的区域,比如hotspot vm的堆划分为年轻代Eden、中生代Survivor和年老代Tenured区域,根据对象存活的年龄放到不同的区域,区域的大小可以通过参数设置。这些讲到gc的时候会详细讲解。
如果要存放的对象超过了堆的最大大小,则会抛出OutOfMemoryError,简称OOM异常。
2、栈
栈主要是运行时存放在方法调用信息(编译器已确定占用空间的东西怎么体现)的区域,栈是线程私有的,每个线程都有一个栈,线程生而栈生,线程死而栈灭。
栈中内存不需要额外收集,每次方法调用完成后都会自动回收。hospot vm中可以通过-Xss设置栈大小,默认是2m。
每次方法调用,都会产生一个栈帧,方法调用结束都会弹出栈帧。栈帧主要包括局部变量表、操作数栈、帧数据区。帧数据区又包括运行时解析常量池会用到的常量池指针、方法返回信息、指向异常的信息(还有什么)
所有栈占用的内存大小怎么计算?虚拟机整个的内存-堆内存-方法区内存-pc计数器-本地方法栈?
如果栈可以动态的在堆中分配,则如果分配不了更多的栈内存的时候会抛出OOM异常,否则会抛出StackOverflowError
3、方法区
方法区存class文件加载到内存后的类型信息,如类型描述符、全限定名、接口、字段、方法、属性信息,还有运行时常量池、指向堆中Class实例和ClassLoader实例的信息。另外还存放jit编译产生的本地代码。
方法区在逻辑上是堆的一部分,但是不同的虚拟机有不同的叫法,hotspot叫做non-heap内存,IBM J9和Jrockit则没有这种叫法。hotspot后续版本也会去掉这种叫法,放到native memory的区域
方法区的类型信息也可以卸载,及gc,但是比较严格,像java动态代理生成的代理类经常会被卸载。类型信息要被卸载必须满足这些条件:a、类型所有实例都被回收了 b、Class对象被回收了 c、加载该类的ClassLoader已经被回收 d、还有什么
该区域也会内存溢出,溢出时候抛出OOM异常,如果jar包太多而方法区内存太小或者运行时动态向常量池添加太多东西,就会抛出OOM
4、本地方法栈
执行本地代码的时候用到的栈,hotspot的本地方法栈和栈是同一块区域。
5、pc计数器
指向当前线程将要指向的下一条指令,线程私有的区域,一个线程有一个pc计数器。该区域不会抛出异常。一个字长
6、Direct Memory
java1.4开始提供了NIO,大量读取数据的时候,不用先把数据拷入jvm内存中,直接从os内存读取。所以该区域不占用jvm的堆内存,通过参数-XX:MaxDirectMemorySize设置该区域大小,如果不设置默认跟堆大小一样大。
该区域会抛出OOM异常,何时?
7、常量池
类文件的常量池装载进内存后同样会形成常量池,这是运行时常量池。与类文件常量池不同的是,运行时常量池在使用的时候需要解析,需要把一些entry的符号引用转化成直接引用。
如3提到,此区域在内存不够用时会抛出OOM。
三、例子
1、堆
先创建一个包含大对象的类
package com.yymt.jvm; public class BigObejct { int[] value; private static final int M1 = 1024 * 1024; public BigObejct() { //4 * 1m = 4m this.value = new int[M1]; } }
循环创建类,注释中-Xmx10m是启动时虚拟机参数,最大堆内存是10m
package com.yymt.jvm.oom; import com.yymt.jvm.BigObejct; public class HeapOOM { /** * -Xmx10m * @param args */ public static void main(String[] args) { BigObejct[] objs = new BigObejct[20]; for(int i = 0;i < 20;i++){ objs[i] = new BigObejct(); } } }
堆溢出,注意此处OutOfMemoryError: Java heap space表明是堆空间溢出
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.yymt.jvm.BigObejct.<init>(BigObejct.java:8) at com.yymt.jvm.oom.HeapOOM.main(HeapOOM.java:15)
2、栈溢出错误StackOverflowError
package com.yymt.jvm.oom; public class StackOverflow { /** * -Xss500k 如果加上此参数则不会出现StackOverflowError * @param args */ public static void main(String[] args) { recursiveInvoke(5000, 1, 1); } public static void recursiveInvoke(int cnt,int param1,int param2){ if(cnt == 0){ return; } int newCnt = cnt - 1; int param3 = param1 + param2; int param4 = param1 - param2; recursiveInvoke(newCnt, param4, param3); } }
不加-Xss参数时候就直接异常了,至少在我的机子上如此;-Xss100k也可以出异常,-Xss500k就正常运行
Exception in thread "main" java.lang.StackOverflowError at com.yymt.jvm.oom.StackOverflow.recursiveInvoke(StackOverflow.java:13) at com.yymt.jvm.oom.StackOverflow.recursiveInvoke(StackOverflow.java:19) ......
3、方法区
3.1、如果系统非常庞大,比如说一个很大的产品,如ERP系统、CRM系统,里边有非常多的jar包,运行期这些jar都要加载到内存中,而如果方法区设置的过小,就会导致OOM。在客户分阶段上线过程中,第一阶段只上部分模块,比如erp系统只上财务模块,第二期上供应链,第三期上hr、制造,如果前期MaxPermSize设置的过小,就会导致后期部署完相关模块运行过程中出现方法区溢出。此处因为系统代码庞大,代码无法上传。注意此处是PermGen space
java.lang.OutOfMemoryError: PermGen space
3.2、如果动态创建无数的类放到内存中同样会出现这个问题
package com.yymt.jvm.oom; 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 PermGenOOM { /** * -XX:MaxPermSize=10m * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 5000000; i++) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(DynClz.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { return arg3.invokeSuper(arg0, arg2); } }); enhancer.create(); Thread.sleep(20); } } }
异常:
Caused by: java.lang.OutOfMemoryError: PermGen space
4、Direct Memory
package com.yymt.jvm.oom; import java.lang.reflect.Field; import sun.misc.Unsafe; public class DirectMemoryOOM { private static final int M1 = 1024 * 1024; /** * @param args * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InterruptedException */ public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InterruptedException { Field unsafeFld = Unsafe.class.getDeclaredFields()[0]; unsafeFld.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeFld.get(null); for (int i = 0; i < 1000000; i++) { unsafe.allocateMemory(M1); Thread.sleep(2); } Thread.sleep(100000); } }
这部分内存的使用情况,目前visualvm工具中是检测不到的
Exception in thread "main" java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method) at com.yymt.jvm.oom.DirectMemoryOOM.main(DirectMemoryOOM.java:24)
发表评论
-
一次Direct buffer memory引发的OutOfMemoryError问题排查
2014-10-28 17:22 0留坑位 -
jvm运行期打印汇编信息
2014-04-09 23:00 3163如果只在jvm参数中加入-XX:+Prin ... -
Mac OSX 10.9 上build openjdk8和openjdk7
2014-03-29 18:29 14316先分享下自己build出来的fastdeb ... -
内存充足情况下应用一直CMS GC的问题分析
2014-03-26 22:39 0前几天日常上线发布后,收到大量的CMS GC ... -
查看java对象在内存中的布局
2014-03-20 22:39 13082接着上篇《一个对象占用多少字节?》中遇到的 ... -
一个对象占用多少字节?
2014-03-18 21:56 35185老早之前写过一篇博客,是关于一个Integ ... -
cpu字长、操作系统字长和jvm中各数据类型占用的字节数关系
2014-03-16 02:05 4731cpu字长是指cpu同时参与运算的二进制位 ... -
cache line对内存访问的影响
2014-03-12 20:48 1388cache line对内存访问的影响很早就 ... -
一次线上问题的排查过程——时钟精度变化导致的cpu占用率高的问题
2013-09-16 21:14 4221最近升级了一次tair(缓存系统)的cli ... -
Kilim源码分析之五 ---- 织入之变量活跃性分析
2013-03-20 21:00 1232/** * In live va ... -
Kilim源码分析之四 ---- 织入之内联subroutine
2013-03-20 20:00 1503小于1.5编译级别时,如果不显示inlin ... -
Kilim源码分析之三 ---- 织入之构造/合并BasicBlock
2013-03-20 19:50 1442上一篇分析 ... -
在编译级别1.4时jvm编译try/catch/finally块的方式
2013-03-12 21:22 1484先上一段很简单,且不考虑健壮性的源码: ... -
ASM4.0源码走读之三 readCode方法分析方法代码
2013-03-09 00:19 1816继第一篇,我们来看看readCode的代码 ... -
ASM4.0源码走读之二 指令的类型
2013-03-08 23:51 1710在深入分析ClassReader.read ... -
ASM4.0源码走读之一
2013-03-08 23:18 1824了解java class ... -
java协程框架----kilim实现机制解析
2013-03-08 16:14 6639java语言处理多任务的模式是基于多线程,java语言级 ... -
Kilim源码分析之二 ---- 织入入口及可织入判断
2013-03-20 19:33 31331、织入入口,配置 1.1、织入入口 ... -
由一个小程序引发的思考 — 关于字段和方法的分派
2011-11-05 14:32 1851面向对象三大特征封装 ... -
JVM学习笔记十四 之 线程模型和锁
2011-10-24 02:30 0os线程模型、jvm线程、java线程调度、状态 线程安全程 ...
相关推荐
本篇JVM学习笔记主要涵盖了以下几个核心知识点: 1. **运行时数据区**: - **程序计数器**:记录当前线程执行的字节码的行号,用于线程恢复执行时跳转到正确位置。 - **Java虚拟机栈**:每个方法执行时创建的栈帧...
Java8 Jdk JVM学习笔记、jdk1.8、SpringBoot; 主要内容为 JVM 内存与垃圾回收、类加载子系统、运行时数据区、本地方法等。适合开发1-3年想对JVM学习的同学。 在之后的开发中,更加详细的了解JVM,可以进行JVM问题...
1. **JVM架构**:JVM主要由类装载器、运行时数据区、执行引擎、本地方法接口和本地库组成。了解每个部分的功能对于优化程序性能至关重要。 2. **类装载机制**:包括加载、验证、准备、解析和初始化五个阶段,确保类...
JVM的学习可以从其基本结构、代码编译和执行过程,以及内存管理和垃圾回收机制三个方面进行深入探讨。 首先,JVM的基本结构分为逻辑结构和物理结构。逻辑结构主要包括Java源码编译器、JVM执行引擎、类加载器等组件...
### JVM学习笔记核心知识点整理 #### 一、引言与背景 随着软件开发技术的不断发展,Java作为一种广泛应用的编程语言,其背后的核心技术——Java虚拟机(JVM)的重要性日益凸显。掌握JVM不仅可以帮助开发者更好地理解...
Java虚拟机(JVM)是Java程序运行的基础,它是一个抽象的计算机系统,负责执行Java字节码。本文将深入探讨JVM的工作...这本《JVM工作原理学习笔记》应包含了这些内容的详细讲解,对于学习和提升JVM相关知识极具价值。
**JVM学习笔记(Java虚拟机)** Java虚拟机(JVM)是Java语言的核心组成部分,它是Java程序运行的平台,负责解释和执行字节码。深入理解JVM对于优化Java应用程序性能至关重要。本笔记将从以下几个方面详细介绍JVM:...
### JVM中篇笔记知识点 #### 一、Class 文件结构 ##### 1. 概述 - **字节码文件的跨平台性** - Java 的跨平台性体现在 "Write Once, Run Anywhere" (WORA),即一次编写,到处运行。Java 语言编写的源代码在编译...
《深入理解JVM:垃圾回收与优化》 在Java编程领域,JVM(Java Virtual Machine)扮演着至关重要的角色,它是Java程序...开发者需要不断学习和实践,才能在实际项目中有效地配置和优化JVM,确保程序的高效稳定运行。
1. **JVM结构**:JVM主要包括类装载器、运行数据区、执行引擎、本地方法接口和本地库。类装载器负责加载类文件,运行数据区存储程序运行时的数据,执行引擎负责执行字节码,本地方法接口用于调用非Java语言编写的...
JVM主要包括以下几个组件:类加载器、运行时数据区、执行引擎、本地方法接口和本地库。理解JVM的工作原理,有助于我们更好地理解和排查程序中的问题。 二、内存管理 JVM内存主要分为堆内存和栈内存两大部分。堆...
《JVM学习笔记》 Java虚拟机(JVM)是Java平台的核心组成部分,它负责运行所有的Java应用程序。这篇笔记将深入探讨JVM的工作原理、内存管理、类加载机制以及优化策略,帮助读者全面理解JVM并提升Java程序的性能。 ...
### JVM学习笔记知识点详解 #### 一、JVM的基本结构 **JVM(Java Virtual Machine,Java虚拟机)**是一种可以执行Java字节码的虚拟机。它为Java提供了平台无关性,使得Java代码可以在任何安装了JVM的平台上运行。 ...
Java虚拟机(JVM)作为Java程序的运行环境,负责管理和分配内存资源。为了更好地理解和掌握JVM内部的工作机制,本篇文章将重点介绍JVM中的几个关键内存区域:程序计数器、Java虚拟机栈、本地方法栈、堆以及方法区。 #...
本文将根据"JVM性能学习笔记思维导图"的主题,详细阐述JVM的主要组成部分,性能调优的关键点以及相关的工具与实践策略。** 1. **JVM结构与内存模型** - **类装载器(ClassLoader)**:负责加载类文件,确保类在运行...
在JVM的学习过程中,策略文件是一个重要的环节,它主要用于安全管理,控制不同代码的权限。本篇笔记将深入探讨Java策略文件的概念、结构以及如何使用。 策略文件是Java安全模型的一部分,它定义了哪些代码可以执行...
《JVM内存管理学习笔记》 在Java世界中,JVM(Java Virtual Machine)是运行所有Java应用程序的核心。深入理解JVM内存管理对于优化程序性能、预防和解决内存泄漏问题至关重要。本文将从JVM内存模型、内存区域划分、...
在分发含有敏感数据或需要在受限制环境中运行的Java应用程序时,代码签名是必不可少的步骤。 在JVM中,当加载签名过的JAR时,它会检查签名的完整性和有效性,如果签名失败,JVM将拒绝加载该JAR,从而保护系统免受...
当方法调用、字段访问或数组操作等指令被执行时,JVM会检查操作数栈中的数据类型是否符合Java语言规范的要求。这种检查是基于每个操作的字节码描述来完成的,以防止非法操作,例如,将一个整数对象赋值给一个字符串...
- **运行时常量池**:是方法区的一部分,存放编译器生成的各种符号引用,包括类和方法的元数据。 - **虚拟机栈**:每个方法执行时创建的栈帧,用于存储局部变量、操作数栈和方法返回信息。栈帧的生命周期与方法...