本人初学java,看到面试官问道JVM的问题蛮多,就学了一点点,拿出来和大家分享,有什么错误的地方,希望大家指出来。
要解决内存溢出的问题,我们说为什么内存溢出。运行一个大型的软件或游戏,所需要的内存空间远远超过了,你主机内安装的内存所承受的大小,就叫内存溢出。
对于虚拟机而言,JVM包括一组寄存器,一个栈,一个垃圾回收堆一个存储方法域。我们的实例对象会放在java堆空间,普通对象存放在栈中,以及方法区,常量池等等,还有本机内存,所以对于内存溢出的问题,我们已经有眉目从哪些地方找到元凶了。
A:java堆溢出
java堆用于存放我们的实例对象,当我们不断的创建对象,并一直持有对象的引用,防止被gc。
测试如下:
[img]package demo;
import java.util.ArrayList;
import java.util.List;
/**
* VM Args:-verbose:gc -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
* */
public class HeapOverFlow {
public static void main(String[] args) {
List<HeapOverFlow> hofs=new ArrayList<HeapOverFlow>();
while(true){
hofs.add(new HeapOverFlow());
}
}
}
[/img]
设置xms为20m,xmx为20m,执行效果如下:
[img]
[GC 17190K->17190K(20352K), 0.0071101 secs]
[GC 18470K->18469K(20352K), 0.0078375 secs]
[GC 18573K->18558K(20352K), 0.0011519 secs]
[Full GC 18558K->18558K(20352K), 0.0546033 secs]
[Full GC 18558K->17808K(20352K), 0.0763401 secs]
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid4784.hprof ...
Heap dump file created [32577359 bytes in 0.842 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2760)
at java.util.Arrays.copyOf(Arrays.java:2734)
at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
at java.util.ArrayList.add(ArrayList.java:351)
at demo.HeapOverFlow.main(HeapOverFlow.java:13)
[/img]
发生这种情况具体还要看是内存泄露还是内存溢出。如果存在内存泄露就要找到泄露点,如果是内存溢出,则需要增加内存空间。至于怎么做,目前还没研究哈。
B:虚拟机栈和本地方法栈溢出
由于在HotSpot虚拟机中并不区分虚拟机栈和本地方法区栈,因此对于HotSpot来说,-Xoss(设置本地方法栈大小)参数是无效的,栈容量由-Xss参数设定。关于虚拟机栈和本地方法区栈,在Java虚拟机规范中描述了两种异常:
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常
如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常
《深入浅出java虚拟机》这本书中谈到单线程的场景下只能浮现StackOverflowError,那我们就先来看看单线程场景下到底会是什么样子。
[img]public class StackOverFlow {
private int stackLength = 1;
private void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable {
StackOverFlow oom = new StackOverFlow();
try {
oom.stackLeak();
} catch (Throwable e) {
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
}[/img]
设置-Xss128k 运行结果如下:
[img]stack length:2402
Exception in thread "main" java.lang.StackOverflowError
at demo.StackOverFlow.stackLeak(StackOverFlow.java:11)
at demo.StackOverFlow.stackLeak(StackOverFlow.java:12)[/img]
通过不断创建线程耗尽内存也可以呈现出OutOfMemoryError异常,由于在windows下会造成死机,这里我就不试了。
C:运行时常量池溢出
向运行时常量池中添加内容最简单的方式就是使用String.intern()方法。由于常量池分配在方法区内,可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量池的容量。
例子:
import java.util.ArrayList;
import java.util.List;
/**
* VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
* @author Administrator
*
*/
public class StaticConstantPoolOF {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
int i = 0;
while (true) {
list.add(String.valueOf(i++).intern());
}
}
}
运行结果如下:
[img][GC 3159K->2263K(5056K), 0.0005486 secs]
[Full GC 2403K->1018K(5056K), 0.0387303 secs]
[Full GC 1018K->1018K(5056K), 0.0416562 secs]
[Full GC 1033K->242K(5056K), 0.0150953 secs]
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
at java.lang.String.intern(Native Method)
at demo.StaticConstantPoolOF.main(StaticConstantPoolOF.java:24)[/img]
D:方法区溢出
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。测试这个区域只要在运行时产生大量的类填满方法区,知道溢出。《深入理解Java虚拟机》借助CGlib直接操作字节码运行时,生成了大量的动态类。
当前主流的Spring和Hibernate对类进行增强时,都会使用到CGLib这类字节码技术,增强的类越多,就需要越大的方法区来保证动态生成的Class可以加载到内存。
[img]import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
*
*/
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 object, Method method,
Object[] args, MethodProxy proxy) throws Throwable{
return proxy.invokeSuper(object, args);
}
});
enhancer.create();
}
}
static class OOMObject {
}
}[/img]
工程中要引入cglib-2.2.2.jar和asm-all-3.3.jar。
方法区的内存溢出问题同样存在jdk6和jdk7版本之间的区别,同运行时常量池内存溢出。
方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收掉,判定条件是非常苛刻的。在经常动态生成大量Class的应用中,需要特别注意类的回收状况。这类场景除了上面提到的程序使用了CGLib字节码增强外,常见的还有:大量JSP或动态生成JSP文件的应用、基于OSGi的应用等。
E:本机直接内存溢出
DirectMemory容量可以通过-XX:MaxDirectMemorySize指定。
import java.lang.reflect.Field;
import sun.misc.Unsafe;
/**
* VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
*
*/
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
/**
* @param args
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws IllegalArgumentException,
IllegalAccessException {
// TODO Auto-generated method stub
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while(true){
unsafe.allocateMemory(_1MB);
}
}
}
该例子还没测试。
分享到:
相关推荐
【JVM内存溢出】指的是Java虚拟机在运行过程中,由于内存分配不当或者内存使用过度导致内存无法正常管理,从而抛出错误的情况。这通常会导致应用程序崩溃或性能急剧下降。在Tomcat这样的Java应用服务器中,内存溢出...
标题中的“关于tomcat乱码以及...综上所述,解决Tomcat的乱码问题需要正确配置字符编码,而处理JVM内存溢出则需优化内存分配和垃圾收集策略。对于MySQL的配置,理解`my.cnf`文件的内容对于数据库的高效运行也至关重要。
6. **了解本机直接内存溢出异常的测试**:通过使用`sun.misc.Unsafe`类操作非堆内存,探索如何触发直接内存溢出异常。 #### 实验实现过程 ##### Java堆内存溢出异常的测试 为了测试Java堆内存溢出异常,通常会...
**JRockit JAVA内存溢出检测的使用** Java内存溢出是开发和运行Java应用程序时常见的问题,可能导致程序崩溃或性能急剧下降。JRockit JVM(Java Virtual Machine)由Oracle公司开发,它提供了强大的内存管理和分析...
虽然Python有内置的垃圾回收机制,但仍然可能出现内存泄漏和内存溢出的问题,影响程序的稳定性和效率。 **一、Python内存泄漏** 内存泄漏通常是由于以下几个原因引起的: 1. **C扩展模块的内存泄漏**:使用C语言...
综上所述,解决Jetty 8内存溢出问题需要综合考虑JVM参数配置、代码优化、资源管理策略以及监控与分析等多个层面。通过对上述知识点的理解和实践,可以有效地预防和解决Jetty 8的内存溢出问题,提高服务的稳定性和...
1. **生成堆转储文件(Heap Dump)**:当Java应用程序出现内存溢出异常时,可以通过JVM参数设置(如`-XX:+HeapDumpOnOutOfMemoryError`)让JVM自动生成堆转储文件,或者通过`jmap`命令手动生成。堆转储文件是分析...
Java内存溢出(Out of Memory,OOM)是Java应用程序中常见的问题,会导致程序崩溃或性能急剧下降。HeapAnalyzer是一款强大的工具,专为分析Java应用程序的内存状况,特别是针对内存溢出问题进行诊断。本文将详细介绍...
MAT,全称Memory Analyzer Tool,是IBM开发的一款强大的JVM内存分析工具,尤其适用于诊断Java应用程序的内存泄漏问题。在Java开发过程中,内存溢出(Out Of Memory)问题常常会导致程序异常终止,而MAT就是解决这类...
### 解决OutOfMemoryError内存溢出 在Java开发过程中,我们经常会遇到`java.lang.OutOfMemoryError`(简称OOM)的问题。这个问题的发生主要是由于JVM内存不足或程序中存在内存泄漏所引起的。本文将深入探讨OOM产生...
jprofiler的使用及联调内存溢出解决方案交流 jprofiler 是一个全功能的 Java 剖析工具,专用于分析 J2SE 和 J2EE 应用程序。它把 CPU、执行绪和内存的剖析组合在一个强大的应用中,提供许多 IDE 整合和应用服务器...
Java内存溢出(Out Of Memory,OOM)是Java应用程序运行时常见的问题,它通常发生在程序对内存需求超过了Java虚拟机(JVM)所能提供的可用内存时。本文将深入探讨Java内存溢出的原因、表现以及如何解决。 1. **Java...
Tomcat内存溢出是由于JVM的虚拟内存默认为128M,当超过这个值时就把先前占用的内存释放,而导致出现HTTP500的错误。当用户执行一个大数据的应用时,系统会提示出错,前台错误为:HTTP Status 500-Dispatch[EAITool] ...
解决内存溢出问题通常需要调整JVM的内存参数,如`-Xms`和`-Xmx`用于设置堆的初始大小和最大大小,以及`-XX:MaxPermSize`(对于较旧的JVM版本)或`-XX:MaxMetaspaceSize`(对于Java 8及以上版本)来控制方法区的大小...
- **Metaspace大小**:监控和调整元空间大小,防止因类加载过多导致的内存溢出。 - **对象创建优化**:减少不必要的对象创建,复用对象,避免短生命周期对象进入老年代。 - **内存泄漏检测**:使用工具检测潜在的...
### JVM内存参数调优 在Java开发过程中,合理地配置JVM(Java虚拟机)的内存参数对于提高程序运行效率、避免内存溢出等问题至关重要。本文将深入探讨JVM内存参数调优的相关知识点,帮助开发者更好地理解并掌握如何...
在Java编程中,内存溢出(Out...总之,解决Java程序内存溢出问题需要深入理解内存管理、JVM参数、垃圾回收以及代码优化等多个方面。通过不断学习和实践,开发者可以有效地预防和解决这类问题,确保程序的稳定性和性能。
在MyEclipse中,可以通过修改`myeclipse.ini`文件来调整JVM参数,从而避免内存溢出问题的发生。具体步骤如下: 1. 打开MyEclipse安装目录下的`myeclipse.ini`文件(例如:`G:\MyEclipse8.5\Genuitec\MyEclipse8.5\...