注册网站免费注册qq邮箱,seo服务销售招聘,什么是外包公司?,网站内部优化策略前言那些使用过 C 或者 C 的读者一定会发现这两门语言的内存管理机制与 Java 的不同。在使用 C 或者 C 编程时#xff0c;程序员需要手动的去管理和维护内存#xff0c;就是说需要手动的清除那些不需要的对象#xff0c;否则就会出现内存泄漏与内存溢出的问题。如果你使用 J…前言那些使用过 C 或者 C 的读者一定会发现这两门语言的内存管理机制与 Java 的不同。在使用 C 或者 C 编程时程序员需要手动的去管理和维护内存就是说需要手动的清除那些不需要的对象否则就会出现内存泄漏与内存溢出的问题。如果你使用 Java 语言去开发你就会发现大多数情况下你不用去关心无用对象的回收与内存的管理因为这一切 JVM 虚拟机已经帮我们做好了。了解 JVM 内存的各个区域将有助于我们深入了解它的管理机制避免出现内存相关的问题和高效的解决问题。下面来讲讲面试中也是Java学习进阶中必备的JVM知识后续还会更新完JVM系列观看的朋友可以转发关注下引出问题在 Java 编程时我们会用到许多不同类型的数据比如临时变量、静态变量、对象、方法、类等等。 那么他们的存储方式有什么不同吗或者说他们存在哪运行时数据区域Java 虚拟机在执行 Java 程序过程中会把它所管理的内存分为若干个不同的数据区域各自有各自的用途。1.程序计数器线程私有的可以看作是当前线程所执行字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。分支、循环、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。这时唯一一个没有规定任何 OOM 异常的区域。2.虚拟机栈虚拟机栈也是线程私有的生命周期与线程相同。栈里面存储的是方法的局部变量、对象的引用等等。在这片区域中规定了两种异常情况当线程请求的栈深度大于虚拟机所允许的深度将抛出 StackOverflowError 异常。当虚拟机栈动态扩展无法申请到足够的内存时会抛出 OOM 异常。3.本地方法栈和虚拟机栈的作用相同只不过它是为 Native 方法服务。HotSpot 虚拟机直接将虚拟机栈和本地方法栈合二为一了。4.堆堆是 Java 虚拟机所管理内存中最大的一块。是所有线程共享的一块内存区域在虚拟机启动时创建。这个区域唯一的作用就是存放对象实例也就是 NEW 出来的对象。这个区域也是 Java 垃圾收集器的主要作用区域。当堆的大小再也无法扩展时将会抛出 OOM 异常。5.方法区方法区也是线程共享的内存区域用于存储已经被虚拟机加载的类信息、常量、静态变量等等。当方法区无法满足内存分配需求时会抛出 OOM 异常。这个区域也被称为永久代。补充虽然上面的图里没有运行时常量池和直接内存但是这两部分也是我们开发时经常接触的。所以给大家补充出来。运行时常量池运行时常量池是方法区的一部分Class 文件中除了有类的版本、字段、方法、接口等描述信息外还有一项信息是常量池用于存放编译期生成的各种字面量和符号引用这部分内容将在类加载后存放到方法区的运行时常量池中。也会抛出 OOM 异常。直接内存直接内存并不是虚拟机运行时数据区的一部分也不是 Java 虚拟机规范中定义的内存区域但是却是NIO 操作时会直接使用的一块内存虽然不受虚拟机参数限制但是还是会受到本机总内存的限制会抛出 OOM 异常。JAVA8 的改变对于方法区它是线程共享的主要用于存储类的信息常量池方法数据方法代码等。我们称这个区域为永久代。大部分程序员应该都见过 java.lang.OutOfMemoryError:PermGen space 异常这里的 PermGen space 其实指的就是方法区。由于方法区主要存储类的相关信息所以对于动态生成类的情况比较容易出现永久代的内存溢出典型的场景是在 JSP 页面比较多的情况容易出现永久代内存溢出。在JDK 1.8中HotSpot 虚拟机已经没有 PermGen space 这个区域了取而代之的是一个叫做Metaspace (元空间)的东西。变化就是移除了方法区增加了元空间与方法区最大的区别是元空间不再虚拟机中而是使用本地内存。默认情况下元空间的大小仅受本地内存限制。这样更改的好处字符串常量存在方法区中容易出现性能问题和内存溢出。类和方法的信息等比较难确定大小因此对于方法区大小的指定比较困难太小容易出现方法区溢出太大容易导致堆的空间不足。方法区的垃圾回收会带来不必要的复杂度并且回收效率偏低(垃圾回收会在下一章给大家介绍)。内存溢出虽然有 JVM 帮我们管理内存但是在实际开发过程中一定还会遇到内存溢出的问题。堆栈方法区都有可能出现内存溢出问题。下面我们就结合几个实际的小例子来给大家展示一下方便大家以后根据不同的情况对内存溢出问题进行快速准确的定位。java.lang.OutOfMemoryError: Java heap space ———java 堆内存溢出此种情况最常见一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露需要通过内存监控软件查找程序中的泄露代码而堆大小可以通过虚拟机参数 -Xms、 -Xmx 等修改。例子在集合中无限加入对象效果受到机器配置影响可以主动更改堆大小方便演示。java.lang.OutOfMemoryError: PermGen space ------java永久代溢出即方法区溢出了一般出现于大量Class 或者 JSP 页面或者采用 CGLIB 等反射机制的情况因为上述情况会产生大量的 Class 信息存储于方法区。此种情况可以通过更改方法区的大小来解决使用类似 -XX:PermSize64m -XX:MaxPermSize256m 的形式修改。另外过多的常量尤其是字符串也会导致方法区溢出因为常量池也是方法区的一部分。例子无限加载 Class需要在 JDK 1.8 之前的版本运行因为1.8将方法区改成了元空间利用了机器的内存最好手动设置 -XX:MaxPermSize将值调小一点。java.lang.StackOverflowError ------ 不会抛 OOM error但也是比较常见的 Java 内存溢出。Java 虚拟机栈溢出一般是由于程序中存在死循环或者深度递归调用造成的栈大小设置太小就会出现此种溢出。可以通过虚拟机参数 -Xss 来设置栈的大小。例子无法快速收敛的递归。总结JVM内存区域划分便于它能够更加高效的管理自身的内存。当程序中出现这种由于JVM造成的内存溢出的情况的时候需要根据不同的情况做不同的分析与处理。最后读到这的朋友可以转发关注下后续还会更新JVM及性能调优系列的精选文章谢谢您的支持