【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众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...
随机推荐
- 【持续更新】JS 时间与日期
JS 的日期时间在项目中是必定会用到的,所以必须掌握. UTC 与 GMT 背景 十七世纪,格林威治皇家天文台为了海上霸权的扩张计画而进行天体观测.1675年旧皇家观测所(Old Royal Obse ...
- android 插件化框架speed-tools
项目介绍: speed-tools 是一款基于代理模式的动态部署apk热更新框架.插件化开发框架: speed-tools这个名字主要指的快速迭代开发工具集的意思. 功能与特性: 1.支持Androi ...
- selenium-Python之鼠标事件
通过click()来模拟鼠标的单击操作,鼠标还具有鼠标右击,双击,悬停甚至鼠标拖动等功能.在webdriver中,将这些鼠标操作方法封装在ActionChains类提供. ActionChains类提 ...
- 如何让Sublime Text编辑器支持新的ABAP关键字
ABAP 7.40推出了许多新的关键字 - keyword,您的Sublime Text可能无法针对这些新关键字实现期望的语法高亮显示(syntax highlight)或者自动完成(auto com ...
- Dijkstra算法——单源最短路算法
一.介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他各个节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 适用于有 ...
- ping 不通。无法访问目标主机
台式机 使用无线网卡 又登录了VPN 有时候访问不了局域网内的主机 解决方案 添加路由即可 window+R 打开运行 输入cmd 然后输入 route add 10.16.1.89 10.13 ...
- CPP-基础:函数指针,指针函数,指针数组
函数指针 函数指针是指向函数的指针变量. 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数.这正如用指针变量可指向整型变量.字符型.数组一样,这里是指向函数.如前所述,C在编译时,每一个 ...
- LeetCode || 递归 / 回溯
呜呜呜 递归好不想写qwq 求“所有情况”这种就递归 17. Letter Combinations of a Phone Number 题意:在九宫格上按数字,输出所有可能的字母组合 Input: ...
- Pacman常用命令 文内搜索吧
列出已经安装的软件包 https://wiki.archlinux.org/index.php/Pacman_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) 维基 pa ...
- shell脚本,批量创建10个系统帐号并设置密码为随机8位字符串。
[root@localhost wyb]# cat user10.sh #!/bin/bash #批量创建10个系统帐号wangyb01-wangyb10并设置密码(密码为随机8位字符串). > ...