【java基础 7】java内存区域分析及常见异常
本篇博客,主要是读书笔记总结,还有就是结合培训分享的总结,没有太多的技术含量!
java 的自动内存管理机制,使得程序员不用为每一个new惭怍的对象写配对的delete/ free代码(回想起C++的编写析构函数,还是挺亲切的)因为内存由虚拟机管理,所以,一旦出现了内存泄漏和溢出等问题,刚好又不了解虚拟机是怎样使用内存的,那排错工作将会变得比较艰难!
一、内存分配
Program counter register:一块比较小的内存空间,作用可以看做是当前线程所执行的字节码的行号指示器。如果线程正在执行的是一个java方法,计数器记录的是正在执行的虚拟机的字节码指令的地址,如果正在执行的是native方法,计数器值设置为空(Undefined) 备注:这是唯一一个在java虚拟机规范中没有规定任何outofmemoryerror的区域。
——详细了解计数器,可以看看CPU阿甘系列文章。
栈:
1,java virtual machine stacks:描述java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(stack frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧的在虚拟机中的入栈和出栈过程。这个区域是线程私有的,它的生命周期和线程相同。
线程私有:java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时候,一个处理器(对于多核即指一个内核)只会执行一条线程中的指令,因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“”线程私有“”的内存。 ——PS:看吧,别以为多线程就一定能提高效率,说的好像切换不需要时间,程序计数器不耗性能似的。(额,看情况哈)
2,native method stacks:与java虚拟机栈相似,区别是:虚拟机栈为执行java方法(字节码)服务,而本地栈则是为虚拟机使用到的native方法服务。
注意:栈区抛出的异常一般有:stackoverflowerror和outofmemoryerror
堆:所有的对象实例以及数组都要在对上分配,原文:the heap is the runtima data area from which memory for all class instances and arrays is allocated.
由于收集器基本采用分代收集算法,所以java heap可分为新生代和老年代,再细致的分。。。。。。。。
一般来说,如果在堆中没有内存完成实例的分配,并且堆也无法再扩展时,将会抛出outofmemoryerror异常
方法区:
1,method area:是各个线程共享的内存区域(与堆一样)它用于存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。在这个区域里面,不需要连续的内存、可以选择固定大小、可扩展,可选择不实现垃圾收集。当方法区无法满足内存分配需求时,将抛出outofmemoryerror异常。
2,runtime constant pool,它属于方法区的一部分,class文件除了有类的版本、字段、方法、接口等信息,还有一项是常量池:用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。 PS:区别class文件中的常量池和运行时常量池。 当常量池无法再向方法区内存申请到内存,抛出outofmemoryerror异常。
二、一般问题解决思路
总体说来,JVM的异常,大体分为两个部分:outofmemoryerror(内存溢出) 和 stackoverflowerror(堆栈溢出)从上述文章来看,异常可以极端简化为两种情况:1,操作系统没有给JVM(各个区)足够的内存——调整JVM的内存大小可解决,通过设置相应参数;2,JVM没有给程序足够的内存——一般而言JVM不会拒绝分配内存,一旦没有足够的内存,那么就是内存用尽,即有程序劫持了空间不释放,改代码。
要想解决问题,先写出以下几段代码先:
2.1,写出一段会造成堆区溢出的代码
分析:堆区存储的是对象实例,所以,要造成堆区溢出,那么就无限制的new出对象实例吧,然后为了防止GC工作,再将这些对象实例,添加到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);
}
}
}
2.2,写出一段会造成栈区溢出的代码
分析:
java虚拟机栈描述java方法执行时的内存模型,如果一个方法不停的调用自己(递归)当深度达到JVM所允许的最大深度时,出错!
public class javaVMStackSof{
private int stackLength=1;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args){
javaVMStackSof oom=new javaVMStackSof();
oom.stackLeak();
}
}
本地方法栈为native方法服务,所以要溢出的话,也是通过递归使用native方法!
2.3,写出一段方法区溢出的代码
方法区是被各个线程共享的内存区域,用于存储被虚拟机加载的类信息等,所以,只要在运行时不停地加载类文件等,就会导致方法区溢出——增强class
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(){
public Object intercept(Object obj,Method method,Object[] args,MethodProxy proxy)throws Throwable{
return proxy.invokeSuper(obj,args);
}
});
enhancer.create();
}
}
static class OOMObject{
}
}
2.4,写出一段常量池溢出的代码
只要新的常量请求不到方法区的内存,就会出错,那么最简单直接的方式,就是在运行时不停的请求内存咯!最常用的就是string.intern()方法
public class juntimeconstantpooloom{
public static void main(String[] args){
List<String> list=new ArrayList<String>();
int i=0;
while(true){
list.add(String.valueOf(i++).intern());
}
}
}
三、总结
这是基本的内存分布分析,知道了怎么写代码会造成内存溢出或者内存消耗,那么当想要去优化的时候,就会轻松很多!在写这个博客的时候,突然想起了我有一次去面试的面试题,唉,现在了解了内存分配之后,才发现我当时做的关于堆栈创建对象的题,好像都错了!
不过,知识本身就是在不断的更新、更正的,现在知道错了,也不算晚,多积累,多学习吧!
【java基础 7】java内存区域分析及常见异常的更多相关文章
- Java基础一篇过(八)常见异常速查
一.引言 开发过程中可能会遇到各种各样的异常,这里还是汇总一些比较典型的异常,有些比较直观的异常如空指针这种就不写了,此文可作为异常速查用. 二.异常大军正在来袭~ IllegalArgumentEx ...
- [转]使用Java Mission Control进行内存分配分析
jdk7u40自带了一个非常好用的工具,就是Java Mission Control.JRockit Misson Control用户应该会对mission control的很多功能十分熟悉,JRoc ...
- Java虚拟机--Java内存区域的划分和异常
Java内存区域的划分和异常 运行时数据区域 JVM在运行Java程序时候会将内存划分为若干个不同的数据区域. 程序计数器 线程私有.可看作是当前线程所执行的字节码的行号指示器,字节码解释器的工作是通 ...
- Java内存区域的划分和异常
Java内存区域的划分和异常 运行时数据区域 JVM在运行Java程序时候会将内存划分为若干个不同的数据区域. 打开百度App,看更多美图 程序计数器 线程私有.可看作是当前线程所执行的字节码的行 ...
- Java基础技术-Java其他主题【面试】
Java基础技术-Java其他主题[面试] Java基础技术IO与队列 Java BIO.NIO.AIO Java 中 BIO.NIO.AIO 的区别是什么? 含义不同: BIO(Blocking I ...
- 黑马程序员:Java基础总结----java注解
黑马程序员:Java基础总结 java注解 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! java注解 lang包中的基本注解 @SuppressWarnings ...
- Java基础:Java的四种引用
在Java基础:java虚拟机(JVM)中,我们提到了Java的四种引用.包括:强引用,软引用,弱引用,虚引用.这篇博客将详细的讲解一下这四种引用. 1. 强引用 2. 软引用 3. 弱引用 4. 虚 ...
- java基础-学java util类库总结
JAVA基础 Util包介绍 学Java基础的工具类库java.util包.在这个包中,Java提供了一些实用的方法和数据结构.本章介绍Java的实用工具类库java.util包.在这个包中,Java ...
- java基础(二)-----java的三大特性之继承
在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...
随机推荐
- WPF学习04:2D绘图 使用Shape绘基本图形
我们将使用Shape进行基本图形绘制. 例子 一个可移动的矩形方框: XAML代码: <Window x:Class="Shape.MainWindow" xmlns=&qu ...
- 获取文件的MD5码(C#)
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace Test ...
- ES-windos环境搭建(2)
下载 打开elasticsearch官网.选择downloads. 选择elasticsearch,并单击Download. 这里我们不选择最新版,而是选择靠前的版本,下拉选择past release ...
- codevs 3096 流输入练习——寻找Sb.VI
时间限制: 1 s 空间限制: 16000 KB 题目等级 : 白银 Silver 题目描述 Description 已知某开放授权人员名叫Serb,由于经常修改各种数据,因此开发人员们都喊他SB ...
- wxwidgets编译及环境配置
wxwidgets编译及环境配置 安装步骤: 到www.CodeBlocks.org下载并安装CodeBlocks,最好下载MinGW版本的,可以省掉安装和配置GCC的麻烦. 到www.wxWidge ...
- IOS Array 排序方法
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) { if ([obj1 integerVal ...
- Hopfield 网络(上)
讲的什么 这部分主要对 Hopfield 网络作一大概的介绍.写了其模型结构.能量函数和网络的动作方式.主要参考了网上搜到的一些相关 PPT. 概述 早在 1982 年,Hopfield 发表的文 ...
- Mac下搜索神兵利器Alfred 3.1.1最新和谐版
http://bbs.feng.com/read-htm-tid-9891194.html 相比Windows而言Mac自带的Spotlight搜索已经非常强大了,尤其是Mac OS Yosemite ...
- CPP-基础:单目运算符重载
关于++运算符前置和后置重载的实现实例: #include <iostream> using namespace std; //创建时钟类 class Clock { public: Cl ...
- python之道07
2.用户输入一个数字,判断一个数是否是水仙花数. 水仙花数是一个三位数, 三位数的每一位的三次方的和还等于这个数. 那这个数就是一个水仙花数, 例如: 153 = 1******3 + 5****** ...