JVM基础

来源:互联网 发布:lb极速网络 编辑:程序博客网 时间:2024/06/16 17:29

Java堆(Heap)

  • 线程共享的,或者说是被栈共享
  • 用来存放new的对象和数组,抛异常OutOfMemoryError
  • 运行时动态分配内存,速度慢,但灵活(为对象分配内存的方式:指针碰撞、空闲列表)
    指针碰撞:内存规整,一般用在Serial,PaeNew等垃圾收集器中,即堆中的新生代中
    空闲列表:内存不规整,一般用在基于Mark-Sweep的CMS垃圾收集器,即堆中的老年代中
  • 不连续的内存区域
  • 有Java虚拟机的自动垃圾回收器(GC)来管理
  • 堆又可以分为新生代和老年代,实际还有一个区域叫永久代,但jdk1.7就已经没有了。
    1、永久代是当jvm启动时就存放的JDK自身的类和接口数据,关闭则释放。
    2、新生代可以分为Eden区和两个幸存区(Survivor),使用复制回收算法

Java栈(Stack)

  • 线程私有,每个线程包含一个栈
  • 用来存放基本类型变量,局部变量,对象的引用;
  • 系统自动分配与回收内存,效率较高,快速,存取速度比堆要快;
  • 是一块连续的内存的区域,有大小限制,超出会栈溢出,抛异常StackOverflowError
  • Java会自动释放掉为该变量所分配的内存空间

方法区

  • 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
  • 又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
  • 方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
  • 空间不足则会引发OutOfMemoryError。

常见问题

1、堆空间被占满

异常: java.lang.OutOfMemoryError: Java heap space
由于所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。
解决:
根据垃圾回收前后情况对比,同时根据对象引用情况(常见的集合对象引用)分析,找到泄漏点。

2、持久代被占满

异常:java.lang.OutOfMemoryError: PermGen space
Perm空间被占满。无法为新的class分配存储空间而引发的异常。Java反射比较常见。主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。
解决: -XX:MaxPermSize=512m

3、堆栈溢出

异常:java.lang.StackOverflowError
说明:一般是递归没返回,或者循环调用造成

4、线程堆栈满

异常:Fatal: Stack size too small
说明:java中一个线程的空间大小是有限制的。JDK5.0以后这个值是1M。与这个线程相关的数据将会保存在其中。但是当线程空间满了以后,将会出现上面异常。
解决:增加线程栈大小。-Xss2m。但此配置无法解决根本问题,还要看代码是否有造成泄漏的部分。

5、系统内存被占满

异常:java.lang.OutOfMemoryError: unable to create new native thread
说明:
这个异常是由于操作系统没有足够的资源来产生这个线程造成的。系统创建线程时,除了要在Java堆中分配内存外,操作系统本身也需要分配资源来创建线程。因此,当线程数量大到一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,就出现这个异常了。
解决:
1. 重新设计系统减少线程数量。
2. 线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程

原创粉丝点击