设置 Java 最大堆大小不会在无限循环程序中引发任何错误

Setting Java Max heap size doesn't throw any error in infinite loop program

我有以下代码..

import java.util.Scanner;
import java.lang.Thread;
class Hello{  
public static void main(String[] args){  
try{
    long count =0;
 for(;;){
     A a = new A();
     count++;

     if(count%100 ==0)
     System.out.println("Created "+ count);

 }
}
catch(Exception ex){
    System.out.println("Exception occured");
    System.out.println(ex);
}}
}

class A{
int a = 10;
String str = generateRandom();
String str1 = generateRandom();
String str2 = generateRandom();
String str3 = generateRandom();
String str4 = generateRandom();
String str5 = generateRandom();
String str6 = generateRandom();
String str7 = generateRandom();
String str8 = generateRandom();
String str9 = generateRandom();
String str10 = generateRandom();
String rst1 = generateRandom();
String rst2 = generateRandom();
String rst3 = generateRandom();
String rst4 = generateRandom();
String rst5 = generateRandom();
String rst6 = generateRandom();
String rst7 = generateRandom();
String rst8 = generateRandom();
String rst9 = generateRandom();
String rst10 = generateRandom();



private static String generateRandom() {
    String aToZ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random rand=new Random();
StringBuilder res=new StringBuilder();
for (int i = 0; i < 17; i++) {
   int randIndex=rand.nextInt(aToZ.length()); 
   res.append(aToZ.charAt(randIndex));            
}
return res.toString();

}

我正在 运行使用以下命令安装 java 应用程序..

java -Xmx100M 你好

我预计它会在一段时间后抛出内存异常,但程序 运行 消耗了几乎 100% CPU 而没有崩溃并且几乎一直只占用 80.66MB。

我知道 -Xmx 只设置堆大小而不是其他程序相关的大小。

如果我们设置-Xmx,处于降级模式的应用程序运行是否会频繁运行宁GC仅占用有限的堆大小?

你的 GC 正在删除对象,因为你没有缓存它们,尝试缓存它们是一个列表而不是每次创建一个新对象并分配给局部变量,这应该会抛出异常。

public static void main(String[] args){
    try {
        long count = 0;
        List<A> list = new ArrayList<A>();
        for (;;) {
            list.add(new A());
            count++;

            if (count % 100 == 0) {
                System.out.println("Created " + count);
            }

        }
    } catch (Exception ex) {
        System.out.println("Exception occured");
        System.out.println(ex);
    }
}

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.lang.Long.toString(Long.java:399) at java.lang.String.valueOf(String.java:3113) at javaapplication3.JavaApplication3.main(JavaApplication3.java:34) C:\Users\Ayat Abu Khadrah\AppData\Local\NetBeans\Cache.2\executor-snippets\run.xml:53: Java returned: 1enter code here BUILD FAILED (total time: 5 minutes 5 seconds)

您保留的对象不超过一个 A,因此所需的内存量不会增加。

for(;;) {
    A a = new A();

} // doesn't need `a` any more.

一个简单的解决方案是永远保留每个对象。

public class Main {
    public static void main(String... args) {

        int count = 0;
        try {
            List<Object> as = new ArrayList<>();
            for (; ; ) {
                as.add(new Object());
                count++;
                if (count % 1000000 == 0)
                    System.out.println(count);
            }
        } catch (OutOfMemoryError e) {
            System.out.println("Created " + count + " objects");
        }
    }
}

我建议 运行将其与 -Xmx1g -Xms1g -verbose:gc

结合使用

注意:由于程序会在死前通过清理来尝试保持 运行ning,因此可能需要很长时间才能放弃。即 GC 的时间随着内存的大小而增加,并且当你开始 运行 低时更频繁。

是的。如果设置 -Xmx,应用程序将 运行 处于降级模式,只占用有限的堆大小,并且您的 GC 会持续执行垃圾回收,因为您没有缓存对象。只需尝试以下代码即可获得预期的异常。

import java.util.Scanner;
import java.lang.Thread;
import java.util.Random;
import java.util.ArrayList;

class Hello{  

    public static void main(String[] args){  
        try{
            long count =0;
            ArrayList<A> x = new ArrayList<A>();

         for(;;){
             A a = new A();
             x.add(a);
             count++;

             if(count%100 ==0)
             System.out.println("Created "+ count);

         }
        }
        catch(Exception ex){
            System.out.println("Exception occured");
            System.out.println(ex);
        }
    }
}


class A{
    int a = 10;
    String str = generateRandom();
    String str1 = generateRandom();
    String str2 = generateRandom();
    String str3 = generateRandom();
    String str4 = generateRandom();
    String str5 = generateRandom();
    String str6 = generateRandom();
    String str7 = generateRandom();
    String str8 = generateRandom();
    String str9 = generateRandom();
    String str10 = generateRandom();
    String rst1 = generateRandom();
    String rst2 = generateRandom();
    String rst3 = generateRandom();
    String rst4 = generateRandom();
    String rst5 = generateRandom();
    String rst6 = generateRandom();
    String rst7 = generateRandom();
    String rst8 = generateRandom();
    String rst9 = generateRandom();
    String rst10 = generateRandom();



    private static String generateRandom() {
        String aToZ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random rand = new Random();
        StringBuilder res=new StringBuilder();
        for (int i = 0; i < 17; i++) {
           int randIndex=rand.nextInt(aToZ.length()); 
           res.append(aToZ.charAt(randIndex));            
        }
        return res.toString();
    }
}

不想玩List的可以用

public static void main(String[] args){
    try {
        long count = 0;
        A current = new A();
        for (;;) {
            current.next = new A();
            current = current.next;
            count++;
            if (count % 100 == 0) {
                System.out.println("Created " + count);
            }
        }
    } catch (Exception ex) {
        System.out.println("Exception occured");
        System.out.println(ex);
    }
}
class A {
A next;
.
.
}