电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

内存溢出场景模拟


发布日期:2018/6/16
 

Java Method Stack 栈溢出实验什么时候会让 Java Method Stack 栈溢出啊?栈的基本特点就是 FILO(First In Last Out)如果 in 的太多而 out 的太少就好 overflow 了而 Java Method Stack 的功能就是保存每一次函数调用时的现场即为入栈函数返回就对应着出栈所以函数调用的深度越大栈就变得越大足够大的时候就会溢出所以模拟 Java Method Stack 溢出只要不断递归调用某一函数就可以

程序源码

// Author Poechant // Blog /poechant // Email zhognchaoustc# (#>@)

// Args verbosegc XssK

package comsinosupermanmain

public class Test {

private int stackLength =

public void stackOverflow() { ++stackLengthstackOverflow()}

public static void main(String[] args) throws Throwable { Test test = new Test()

try { teststackOverflow()} catch (Throwable e) { Systemoutprintln(stack length + teststackLength)throw e}运行结果

stack length Exception in thread main javalangStackOverflowError at comsinosupermanmainTeststackOverflow(Testjava

at comsinosupermanmainTeststackOverflow(Testjava

……

Java Method Stack 内存溢出实验Heap 内存溢出

堆是用来存储对象的当然对象不一定都存在堆里(由于逃逸技术的发展)那么堆如果溢出了一定是不能被杀掉的对象太多了模拟 Heap 内存溢出只要不断创建对象并保持有引用存在即可

程序源码

// Author Poechant // Blog /poechant // Email zhongchaoustc# (#>@)

// Args verbosegc Xmxm Xmsm

package comsinosupermanmain

import javautilArrayListimport javautilList

public class Test {

private static class HeapOomObject { }

public static void main(String[] args) { List<HeapOomObject> list = new ArrayList<HeapOomObject>()while (true) { listadd(new HeapOomObject())}运行结果

[GC K>K(K) secs] [GC K>K(K) secs] [GC K(K) secs] [Full GC K>K(K) secs] [Full GC K>K(K) secs] [GC K(K) secs] [Full GC K>K(K) secs] [Full GC K>K(K) secs] [Full GC K>K(K) secs] [GC K(K) secs] [Full GC K>K(K) secs] [Full GC K>K(K) secs] [Full GC K>K(K) secs] Exception in thread main javalangOutOfMemoryError Java heap space at comsinosupermanmainTestmain(Testjava

Method Area 内存溢出也就是 Nonheap是用来存储 Object Class Data常量静态变量JIT 编译后的代码等如果该区域溢出则说明某种数据创建的实在是太多了模拟的话可以不断创建新的 class直到溢出为止

以下代码使用到 cglibjar 和 asmalljar

程序源码

package comsinosupermanmain

import javalangreflectMethod

import netsfcglibproxyEnhancerimport netsfcglibproxyMethodInterceptorimport netsfcglibproxyMethodProxy

public class Test { static class MethodAreaOomObject { } public static void main(String[] args) { while(true){ Enhancer enhancer = new Enhancer()enhancersetSuperclass(MethodAreaOomObjectclass)enhancersetUseCache(false)enhancersetCallback(new MethodInterceptor() { public Object intercept(Object obj Method method Object[] argsMethodProxy proxy) throws Throwable { return proxyinvoke(obj args)} })enhancercreate()}运行结果

Exception in thread main reCodeGenerationException javalangreflectInvocationTargetException——>null at reAbstractClassGeneratorcreate(AbstractClassGeneratorjava

at netsfcglibproxyEnhancercreateHelper(Enhancerjava

at netsfcglibproxyEnhancercreate(Enhancerjava

at comsinosupermanmainTestmain(Testjava

Caused by javalangreflectInvocationTargetException at sunreflectGeneratedMethodAccessorinvoke(Unknown Source)

at sunreflectDelegatingMethodAccessorImplinvoke(DelegatingMethodAccessorImpljava

at javalangreflectMethodinvoke(Methodjava

at reReflectUtilsdefineClass(ReflectUtilsjava

at reAbstractClassGeneratorcreate(AbstractClassGeneratorjava

…… more Caused by javalangOutOfMemoryError PermGen space at javalangClassLoaderdefineClass(Native Method)

at javalangClassLoaderdefineClassCond(ClassLoaderjava

at javalangClassLoaderdefineClass(ClassLoaderjava

…… more Runtime Constant Pool in Method Area 内存溢出在运行时产生大量常量就可以实现让 Method Area 溢出的目的运行是常量可以用 String 类的 intern 方法不断地产生新的常量

程序源码

package comsinosupermanmain

import javautilArrayListimport javautilList

public class Test { public static void main(String[] args) { List<String> list = new ArrayList<String>()int i = while (true) { listadd(StringvalueOf(i++)intern())}运行结果

Exception in thread main javalangOutOfMemoryError PermGen space at javalangStringintern(Native Method)

at comsinosupermanmainTestmain(Testjava

结语在实际编码中要尽量避免此类错误不过大多数程序设计的结构比这里的示例要复杂的多使得问题被隐藏但 JVM 的内存溢出问题本质上大都可归结为以上这几种情况

上一篇:JROCKIT 5.0——轻松玩转JVM

下一篇:JBuilder 2005代码审查功能体验(1)