【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众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...
随机推荐
- MySql数据库的相关操作
SQL(Structred Query Language)结构化查询语言:和数据库交互的语言,进行数据库管理的语言. 一.数据库的操作: 1.查询所有数据库: show databases; 2.创建 ...
- C语言中的fprintf函数详解
fprintf 功能 传送格式化输出到一个文件中 用法 #include stdio.h int fprintf( FILE *stream, const char *format,...); f ...
- C语言中的二级指针(双指针)
原创作品,转载请标明出处http://blog.csdn.net/yming0221/article/details/7220688 C语言更多查看 C语言使用注意事项(一) C语言使用注意事项(二) ...
- COGS 2211. [BZOJ3653]谈笑风生
★★★★ 输入文件:laugh.in 输出文件:laugh.out 简单对比时间限制:3 s 内存限制:512 MB [问题描述] 设T 为一棵有根树,我们做如下的定义: • 设a和b ...
- (三)SpringMVC之常用注解
SpringMVC的常用注解 注解 说明 @Controller 用于说明这个类是一个控制器 @RequestMapping 用于注释一个控制器类或者控制器类的方法 @RequestParam 用于将 ...
- make 与makefile(会不会写 makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。)
跟我一起写 Makefile /**/ 陈皓 (CSDN) 概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉 ...
- html备忘录
上传文件 <form action="/ajax/" method="post" enctype="multipart/form-data&qu ...
- Mybatis generator自动生成代码包括实体,dao,xml文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration ...
- OpenCV2:第八章 界面事件
一.简介 OpenCV中提供了程序界面中的鼠标和键盘事件 二.鼠标事件 // 设置鼠标回调函数 void setMouseCallback ( const string& winname, ...
- H3C交换机系统时间设置漏洞
H3C交换机系统时间设置存在漏洞 1. 背景说明 由于在编写<主机房网络延伸实施方案>,调试H3C S5120S-28P-EI交换机时,发现交换机设置成现在的时间后,导致本地用户通过ssh ...