JVM内存设置,各个参数含义和设置后不起作用问题
2018-01-11 16:00
351 查看
这两天才来公司,遇到很棘手的问题,把公司项目下载下来后无法运行,报错内存溢出问题,然后网上一大堆问题的答案,按照网上的答案解决了tomcat:java.lang.OutOfMemoryError: PermGen space问题,但是后面还有tomcat:java.lang.OutOfMemoryError: Java heap space问题。按照网上的说法设置并没有解决我的问题,于是开始太多JVM内存机制。在这里终结一下怎样解决的问题,希望能帮助自己和他人。如有错误,请大佬指出。
首先来看一下JVM内存有哪些区域,主要的作用是什么?(摘自http://blog.csdn.net/zhoudaxia/article/details/26454421/)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/26/d9cfea4b7fc2d42614a666e06ec13825)
图 4: 运行时数据区
运行时数据区是在JVM运行的时候操作系统所分配的内存区。运行时内存区可以划分为6个区域。在这6个区域中,一个PC Register,JVM stack 以及Native Method Statck都是按照线程创建的,Heap,Method Area以及Runtime Constant Pool都是被所有线程公用的。
PC寄存器(PC register):每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。PC寄存器里保存有当前正在执行的JVM指令的地址。
JVM 堆栈(JVM stack):每个线程启动的时候,都会创建一个JVM堆栈。它是用来保存栈帧的。JVM只会在JVM堆栈上对栈帧进行push和pop的操作。如果出现了异常,堆栈跟踪信息的每一行都代表一个栈帧立的信息,这些信息是通过类似于printStackTrace()这样的方法来展示的。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/26/91ecc9b66ecf1c9388b057bc1e235a1e)
图 5: JVM堆栈
--- 栈帧(stack frame):每当一个方法在JVM上执行的时候,都会创建一个栈帧,并且会添加到当前线程的JVM堆栈上。当这个方法执行结束的时候,这个栈帧就会被移除。每个栈帧里都包含有当前正在执行的方法所属类的本地变量数组,操作数栈,以及运行时常量池的引用。本地变量数组的和操作数栈的大小都是在编译时确定的。因此,一个方法的栈帧的大小也是固定不变的。
--- 局部变量数组(Local variable array):这个数组的索引从0开始。索引为0的变量表示这个方法所属的类的实例。从1开始,首先存放的是传给该方法的参数,在参数后面保存的是方法的局部变量。
--- 操作数栈(Operand stack):方法实际运行的工作空间。每个方法都在操作数栈和局部变量数组之间交换数据,并且压入或者弹出其他方法返回的结果。操作数栈所需的最大空间是在编译期确定的。因此,操作数栈的大小也可以在编译期间确定。
本地方法栈(Native method stack):供用非Java语言实现的本地方法的堆栈。换句话说,它是用来调用通过JNI(Java Native Interface Java本地接口)调用的C/C++代码。根据具体的语言,一个C堆栈或者C++堆栈会被创建。
方法区(Method area):方法区是所有线程共享的,它是在JVM启动的时候创建的。它保存所有被JVM加载的类和接口的运行时常量池,成员变量以及方法的信息,静态变量以及方法的字节码。JVM的提供者可以通过不同的方式来实现方法区。在Oracle 的HotSpot JVM里,方法区被称为永久区或者永久代(PermGen)。是否对方法区进行垃圾回收对JVM的实现是可选的。
运行时常量池(Runtime constant pool):这个区域和class文件里的constant_pool是相对应的。这个区域是包含在方法区里的,不过,对于JVM的操作而言,它是一个核心的角色。因此在JVM规范里特别提到了它的重要性。除了包含每个类和接口的常量,它也包含了所有方法和变量的引用。简而言之,当一个方法或者变量被引用时,JVM通过运行时常量区来查找方法或者变量在内存里的实际地址。
堆(Heap):用来保存实例或者对象的空间,而且它是垃圾回收的主要目标。当讨论类似于JVM性能之类的问题时,它经常会被提及。JVM提供者可以决定怎么来配置堆空间,以及不对它进行垃圾回收。
我这里的异常tomcat:java.lang.OutOfMemoryError: Java heap space是堆空间不足,接着来看设置JVM的参数和各个参数的含义。(摘自:http://blog.csdn.net/shenhonglei1234/article/details/54950663)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/26/fceac64df8beacb7eca97da1ed0440ab)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/26/3298dac2879d3ef7506b1e89b968feb8)
上图中,刻画了Java程序运行时的堆空间,可以简述成如下2条
1.JVM中堆空间可以分成三个大区,新生代、老年代、永久代
2.新生代可以划分为三个区,Eden区,两个幸存区
在JVM运行时,可以通过配置以下参数改变整个JVM堆的配置比例
接着我在myeclipse.ini配置文件中配置参数(公司老员工给我的配置参数)
-Xms1024m
-Xmx2048m
-XX:MaxPermSize=512m
-XX:ReservedCodeCacheSize=64m
重启项目,然而还是tomcat:java.lang.OutOfMemoryError: Java heap space问题,很郁闷,应该是对的啊。最终我使用jdk里面的工具(jdk安装目录下bin中的)jvisualvm工具(直接双击,前提是tomcat运行状态,才能选择连接到tomcat),连接tomcat后查看内存参数,发现我的虚拟机只有256M的内存(下图是改了过后,有1581252608b)。不应该啊,我明明配置了的啊!!
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/26/faeacb6785b59a33a1be2cd64c023960)
然后我把-Xmx2048m改成了-Xmx1024m,自从运行就好了,他就好了,很少惊讶,不知道为什么,但是最后发现只要我的-Xms和-Xmx参数设置为一样大小就会起作用,具体原因不详
首先来看一下JVM内存有哪些区域,主要的作用是什么?(摘自http://blog.csdn.net/zhoudaxia/article/details/26454421/)
运行时数据区(Runtime Data Areas)
图 4: 运行时数据区
运行时数据区是在JVM运行的时候操作系统所分配的内存区。运行时内存区可以划分为6个区域。在这6个区域中,一个PC Register,JVM stack 以及Native Method Statck都是按照线程创建的,Heap,Method Area以及Runtime Constant Pool都是被所有线程公用的。
PC寄存器(PC register):每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。PC寄存器里保存有当前正在执行的JVM指令的地址。
JVM 堆栈(JVM stack):每个线程启动的时候,都会创建一个JVM堆栈。它是用来保存栈帧的。JVM只会在JVM堆栈上对栈帧进行push和pop的操作。如果出现了异常,堆栈跟踪信息的每一行都代表一个栈帧立的信息,这些信息是通过类似于printStackTrace()这样的方法来展示的。
图 5: JVM堆栈
--- 栈帧(stack frame):每当一个方法在JVM上执行的时候,都会创建一个栈帧,并且会添加到当前线程的JVM堆栈上。当这个方法执行结束的时候,这个栈帧就会被移除。每个栈帧里都包含有当前正在执行的方法所属类的本地变量数组,操作数栈,以及运行时常量池的引用。本地变量数组的和操作数栈的大小都是在编译时确定的。因此,一个方法的栈帧的大小也是固定不变的。
--- 局部变量数组(Local variable array):这个数组的索引从0开始。索引为0的变量表示这个方法所属的类的实例。从1开始,首先存放的是传给该方法的参数,在参数后面保存的是方法的局部变量。
--- 操作数栈(Operand stack):方法实际运行的工作空间。每个方法都在操作数栈和局部变量数组之间交换数据,并且压入或者弹出其他方法返回的结果。操作数栈所需的最大空间是在编译期确定的。因此,操作数栈的大小也可以在编译期间确定。
本地方法栈(Native method stack):供用非Java语言实现的本地方法的堆栈。换句话说,它是用来调用通过JNI(Java Native Interface Java本地接口)调用的C/C++代码。根据具体的语言,一个C堆栈或者C++堆栈会被创建。
方法区(Method area):方法区是所有线程共享的,它是在JVM启动的时候创建的。它保存所有被JVM加载的类和接口的运行时常量池,成员变量以及方法的信息,静态变量以及方法的字节码。JVM的提供者可以通过不同的方式来实现方法区。在Oracle 的HotSpot JVM里,方法区被称为永久区或者永久代(PermGen)。是否对方法区进行垃圾回收对JVM的实现是可选的。
运行时常量池(Runtime constant pool):这个区域和class文件里的constant_pool是相对应的。这个区域是包含在方法区里的,不过,对于JVM的操作而言,它是一个核心的角色。因此在JVM规范里特别提到了它的重要性。除了包含每个类和接口的常量,它也包含了所有方法和变量的引用。简而言之,当一个方法或者变量被引用时,JVM通过运行时常量区来查找方法或者变量在内存里的实际地址。
堆(Heap):用来保存实例或者对象的空间,而且它是垃圾回收的主要目标。当讨论类似于JVM性能之类的问题时,它经常会被提及。JVM提供者可以决定怎么来配置堆空间,以及不对它进行垃圾回收。
我这里的异常tomcat:java.lang.OutOfMemoryError: Java heap space是堆空间不足,接着来看设置JVM的参数和各个参数的含义。(摘自:http://blog.csdn.net/shenhonglei1234/article/details/54950663)
上图中,刻画了Java程序运行时的堆空间,可以简述成如下2条
1.JVM中堆空间可以分成三个大区,新生代、老年代、永久代
2.新生代可以划分为三个区,Eden区,两个幸存区
在JVM运行时,可以通过配置以下参数改变整个JVM堆的配置比例
1.JVM运行时堆的大小 -Xms堆的最小值 -Xmx堆空间的最大值 2.新生代堆空间大小调整 -XX:NewSize新生代的最小值 -XX:MaxNewSize新生代的最大值 -XX:NewRatio设置新生代与老年代在堆空间的大小 -XX:SurvivorRatio新生代中Eden所占区域的大小 3.永久代大小调整 -XX:MaxPermSize 4.其他 -XX:MaxTenuringThreshold,设置将新生代对象转到老年代时需要经过多少次垃圾回收,但是仍然没有被回收
接着我在myeclipse.ini配置文件中配置参数(公司老员工给我的配置参数)
-Xms1024m
-Xmx2048m
-XX:MaxPermSize=512m
-XX:ReservedCodeCacheSize=64m
重启项目,然而还是tomcat:java.lang.OutOfMemoryError: Java heap space问题,很郁闷,应该是对的啊。最终我使用jdk里面的工具(jdk安装目录下bin中的)jvisualvm工具(直接双击,前提是tomcat运行状态,才能选择连接到tomcat),连接tomcat后查看内存参数,发现我的虚拟机只有256M的内存(下图是改了过后,有1581252608b)。不应该啊,我明明配置了的啊!!
然后我把-Xmx2048m改成了-Xmx1024m,自从运行就好了,他就好了,很少惊讶,不知道为什么,但是最后发现只要我的-Xms和-Xmx参数设置为一样大小就会起作用,具体原因不详
相关文章推荐
- jvm内存参数设置
- 关于设置JVM内存大小的问题
- 设置eclipse启动参数解决内存不足问题
- JVM 各种内存参数设置
- eclipse.ini内存设置各参数含义
- JVM常见内存设置参数
- java jvm GC 各个区内存参数设置
- 关于设置Java虚拟机(JVM)的内存问题
- 配置eclipse.ini、jvm参数配置说明、解决eclipse卡死问题、eclipse内存配置
- 设置eclipse启动参数解决内存不足问题
- [z]TOMCAT内存_JVM参数设置解决溢出
- JVM内存的设置(解决eclipse下out of memory问题)
- jvm(2)-JVM内存的设置(解决eclipse下out of memory问题)
- Java JVM:内存结构和相关参数含义
- 记录JVM内存模型,参数含义和优化
- Tomcat JVM内存参数设置
- JVM调优-java虚拟机内存模型及参数设置
- JVM内存的设置(解决eclipse下out of memory问题)
- JVM 内存参数设置
- JVM调优-java虚拟机内存模型及参数设置