兄弟们一定谨慎测试,小心你的电脑的jdk崩掉。接下来就直接将测试代码放在下面,接着上一个文章的描述测试各种内存溢出导致的区域性问题,具体的解释在代码注释中可以查看。
1、heap堆内存溢出
public class heap {
/*堆内存爆出的溢出异常测试,一般8以后的JDK不会产生类似问题,其实只需要不断创造实力对象就可以!原因是单个对象的内存太小*/
static class heap1{
}
public static void main(String[] args) {
ArrayList<heap1> arrayList = new ArrayList<>();
while(true){
/*不断地向数组列表里添加新对象,直至堆内存溢出*/
arrayList.add(new heap1());
}
}
}
2、方法区的字符串常量池内存溢出
public class permGen {
/*测试方法区内存溢出*/
public static void main(String[] args) {
Set<String> set = new HashSet<>();
short i = 0;
while(true){
/*intern方法返回的位置在字符串常量池中的引用上,在虚拟机对堆的分区来讲,他应该属于老年代区*/
set.add(String.valueOf(i++).intern());
}
}
}
3、虚拟机栈内存扩展异常
public class SEfM {
/*虚拟机栈的内存溢出,只需要实现方法的互调就能达到*/
private int dosLength=0;
public void dos(){
dosLength++;
dos();
}
public static void main(String[] args) {
SEfM sEfM = new SEfM();
try {
sEfM.dos();
}catch (StackOverflowError error){
System.out.println("此时虚拟机栈局部变量表的一个slot槽大小约为:"+sEfM.dosLength);
throw error;
}
}
}
4、本地方法栈栈帧内扩展异常
public class SEfM1 {
/*本地方法栈的内存溢出测试,主要运用定义变量的方法使本地方法栈的单个栈帧内存溢出*/
private static int stackLength = 0;
public static void test() {
long user1, user2, user3;
stackLength++;
test();
user1 = user2 = user3 = 0;
}
public static void main(String[] args) {
try {
test();
}catch (StackOverflowError error){
System.out.println("此时本地方法栈的单个栈帧大小约为:"+stackLength);
throw error;
}
}
}
5、多线程宕机(堆内存溢出或是虚拟机栈内存扩展异常)
public class SEfM1 {
/*本地方法栈的内存溢出测试,主要运用定义变量的方法使本地方法栈的单个栈帧内存溢出*/
private static int stackLength = 0;
public static void test() {
long user1, user2, user3;
stackLength++;
test();
user1 = user2 = user3 = 0;
}
public static void main(String[] args) {
try {
test();
}catch (StackOverflowError error){
System.out.println("此时本地方法栈的单个栈帧大小约为:"+stackLength);
throw error;
}
}
}
6、Enhaner生成器代理导致的方法区内存溢出(详见AOP底层原理那一文章对于cglib动态代理的相关解释)
public class cglib {
/*采用不断创建动态代理增强生成器来占用,由于方法区中存储的是静态变量,常量,字面量,类的类型信息,字节码文件的代码等
* 其中我们的代理增强器会在被增强类的方法中添加增强的信息,所以方法区会不断的增加内存的使用,从而实现方法区的内存溢出*/
public static void main(String[] args) {
while (true){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(active.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return methodProxy.invokeSuper(objects,args);
}
});
enhancer.create();
}
}
static class active{
}
}
7、测试String:intern();方法返回引用的位置
public class intern {
public static void main(String[] args) {
/*测试string:intern();返回的引用是否在字符串常量池且这个常量池已经转移到java堆中,如果一致返回true*/
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1);
System.out.println(str1.intern()==str1);
String str2 = new StringBuilder("sta").append("tic").toString();
System.out.println(str2.intern()==str2);
}
}