Java 内存区域与内存溢出异常
来源:互联网 发布:淘宝卡dnf称号 编辑:程序博客网 时间:2024/04/30 13:36
一.运行时数据区域
1 . 程序计数器(Program Counter Register):
是一块较小内存空间,它可看作是当前线程所执行的字节码的行号指示器。各线程都会享有自己独立的程序计数器,这样保证线程之前计数据器互不影响,所以这类内存区域为“线程私有”的内存。
2 . java虚拟机栈(Java Virtual Machine Stacks):
也是线程私有的,它的生命同期与线程相同,它描述的是Java方法执行的内存模型:每个方法在运行的时候会创建一个栈桢用于存储局部变量表、操作数栈、动态链接、方法出口等。在该内存区域有两种异常情况:StackOverflowError,当线程请求的栈深度超出虚拟机所允许的深度地抛出该异常;OutOfMemoryError,若虚拟机栈可动态扩展的,而当扩展时无法申请到足够的内存就会抛出该异常。
3 .本地方法栈
与虚拟机栈很相似,区别是虚拟机栈为虚拟机执行Java方法服务,本地方法栈则为虚拟机执行Native方法服务
4 .Java 堆
Java堆是虚拟机管理的内存中最大的一块,是被所有线程共享的一块内存区域,在虚拟机启动地创建,此内存区域唯一目的就是存放对象实例。Java堆是垃圾收集顺管理的主要区域,因此也被称做”GC堆“。由于现在收集器基本都采用分代码收集算法,所以Java堆又可细分为:新生代和老年代,再细致一点又有:Eden空间、FormSurvivor空间、To Survivor空间。如此划分的目的是为了更好的回收内存,或者更快的分配内存。
5 .方法区
方法区与Java堆一样是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。它有一个别名叫Non-Heap(非堆),目的大概是与Java堆区分开来。在HotSpot虚拟机上又被称为”永久代“。而我经常使用的虚拟机就是HotSpot,永久大小可通过下面参数进行配制:
-XX:PermSize来指定初始化是永久代大小和
-XX:MaxPermSize来指定永久代最大内存。
当方法区无法满足内存灵机一动需求时,将抛出OutOfMemoryError异常。
6 .运行时常量池
运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放 编译期生成的各种字面量和符号 引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。一般来说,除了保存Class文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。
7 .直接内存
在JDK1.4中新加入NIO(New Input/Output)类,引入了一种基于通道与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过 一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中提高性能,因为避免了在Java堆和Native堆中来回复制数据。
二对象创建
1、遇到new指令时,首先在常量池中寻找该在的符号引用,并且检查这个符号引用代表 类是否加载、解析和初始经过,如果没有,那执行相应加载过程。
2、虚拟机为新生对象分配内存。所需内存大小在类加载完成后即可完全确定。虚拟机需从堆中划分相同大小的内存空间。划分方式:指针碰撞和空闲列表,使用哪种方式是由所采用的器是否带有压缩整理功能决定。由于对象创建非常频繁的,在并发情况下并不是线程安全的。解决这个问题有两种方案:一种,对分配内存空间的动作进行同步处理;另一种按线程划分在不同空间中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲TLAB。虚拟机是否使用TLAB,可通过:
-XX:+/-UseTLAB参数来设定。
3、将分配到的内存空间都初始化为零值,这步操作就是Java对象属性默认值的来源;
4、设置对象头,如对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、GC分代年龄等信息。
三、内存泄漏与内存溢出
1 .内存泄漏
是指,为对象分配了内存空间后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak会最终会导致out of memory!
2 .内存溢出
是指,为对象申请内容空间时,无法申请到足够空间而抛出OutOfMemoryError。
3 .隐式泄漏
是指,一个线程或方法长时间运行在虚拟机中,导致与该线程相关的内存区域不能及时释放,但当线程或方法一旦运行完成,与线程相关的内在区域即可释放。
总结:从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到
四、JVM常用参数
-Xms40m #指虚拟机启动时即创建40M的堆空间-Xmx512m #指堆了大值为512M-XX:MaxPermsize=256m #指永久代最大值为256M。 -Xverify:none #禁止字节码验证过程-XX:+DisableExplicitGC #屏蔽System.gc()操作。-Xoss40m #设置本地方法栈大小,这里乱写的。-Xss1024k #设置栈容量-XX:HeapDumpOnOutOfMemoryError #让虚拟机在出现内存逆风异常地Dump出当前的内存堆转存储快照。-XX:PretenureSizeThreshold=2m #申请对象大于2M时直接进入老年代-XX:+DisableExplicitGC ##禁用系统中的System.gc()-XX:+BackgroundCompilation #启用JIT编译优化-Xloggc:/home/xieyu/logs/gc.log #将常量GC日志输出到文件-XX:CMSInitiatingOccupancyFraction=70 ##当老年代使用率达70%之后启动CMS GC
垃圾收集器选择
-XX:+UseConcMarkSweepGC
- java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- JAVA内存区域与内存溢出异常
- Java 内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- Java内存区域与内存溢出异常
- JAVA内存区域与内存溢出异常
- 448. Find All Numbers Disappeared in an Array
- POJ 2456 Aggressive cows
- Android多线程操作sqlite数据库连接池框架的一种设计思路
- 设计模式笔记二十一:状态模式
- PAT A1113 integer set partition (25)
- Java 内存区域与内存溢出异常
- 18_使用canvas元素
- VUWE——又一个移动端Vue2组件库
- 19_使用canvas元素
- Java集合框架(上)
- 20_使用拖放
- Android Studio使用git
- APUE读书笔记---进程间通信之POSIX共享内存区
- 使用ES6的新特性Proxy来实现一个数据绑定实例