gpt4 book ai didi

java - Java 中对象实例的上限

转载 作者:行者123 更新时间:2023-11-30 10:12:57 24 4
gpt4 key购买 nike

我正在试验对象实例,因为我想了解是否存在为单个 Java 进程定义的最大对象实例数量。所以我简单地创建了一个对象,它像这样从构造函数中递归地调用自己:

public class A{

private A a;

public A(){
a = new A();
}
}

还有一个像这样的主类:

public class random {
public static void main(String[] args) {
A a = new A();
}
}

这显然导致了 Stack Overflow 异常。谷歌搜索后,我发现每个 Java 线程都有自己的堆栈。那么,为什么不在我原来的线程溢出之前生成一个新线程呢?所以我写了这个:

public class A{

private A a;
private B b;

public A(int i, int lim){
if (i < lim)
a = new A(i + 1, lim, bufferedWriter);
else{
t = new Thread(b = new B(lim));
t.start();
}
}
}

像这样的可运行对象:

public class B implements Runnable {

private int lim;
private A a;

public B(int lim) {
this.lim = lim;
}

@Override
public void run() {
a = new A(lim, lim + 2500);
}
}

我怀疑它会再次抛出异常或由于 RAM 不足而崩溃(这就是为什么我让任务管理器保持打开状态,准备终止进程)。几分钟后,我很惊讶地发现 RAM 使用情况没有明显变化,我也没有发现任何异常。所以我在eclipse中检查了我的运行配置,它也没有改变并设置为默认值。

为了进一步深入了解这个主题,我决定开始计算实例。第一次尝试使用简单的“System.out.println”是行不通的,因为运行 system.out-stream 的线程会简单地溢出。所以我决定将计数写入文件,每个线程一个文件。

我的类(class)现在看起来像这样:

主要内容:

public class random {

public static void main(String[] args) {
try {
A a = new A(0, 2500, new BufferedWriter(new FileWriter(new File(0 + " - " + 2500))));
} catch (IOException e) {
e.printStackTrace();
}
}
}

答:

public class A {

private A a;
private Thread t;
private B b;

public A(int i, int lim, BufferedWriter bufferedWriter) {
try {
bufferedWriter.write(i + "\n");
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
if (i < lim)
a = new A(i + 1, lim, bufferedWriter);
else{
t = new Thread(b = new B(lim));
t.start();
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

乙:

public class B implements Runnable {

private int lim;
private A a

public B(int lim) {
this.lim = lim;
}

@Override
public void run() {
try {
a = new A(lim, lim + 2500, new BufferedWriter(new FileWriter(new File(lim + " - " + (lim + 2500)))));
} catch (IOException e) {
e.printStackTrace();
}
}
}

同样,令人惊讶的是我的 RAM 使用率非常稳定。我更担心我的磁盘存储,因为大约 2 分钟后我的小程序创建了超过 6500 个文件(所以每秒约 33 个文件),每个文件中恰好有 2500 个数字(我想......我没有计算)总数达到 16.260.000。 Ofc 它不足以填满我的磁盘,但我当时停止了它。

好的,如果你读到这里,你要么对我的小实验很感兴趣,要么真的想回答我的问题……所以这里是:

我从未设置任何对 null 的引用,我创建的任何实例都被我的主类间接引用。所以我认为垃圾收集器不会触及我宝贵的实例(对吧?)。我的 RAM 怎么没有完全填满?或者至少 JVM 如何没有达到其分配的 RAM 限制?如果我相信我的计数器,我有超过 1600 万个对象实例,甚至不包括 B 的实例,如果我允许的话,它每秒会创建 83.000 个以上的对象引用继续前进。

此外,当我们讨论这个主题时:一个简单的对象会用掉多少 RAM?我知道它显然与对象中引用和使用的变量和数量有关,但我们只说一个完全空的对象。它会使用多少内存?

PS:我知道我可以通过在我的主类中同时启动线程来加速我的程序,但我的(主要)意图不是尽可能快地用完我所有的磁盘空间,而是计算对象实例:)

最佳答案

我认为你的测试的问题是你的对象仍然被垃圾收集。如果您创建一个线程并且在它完成其工作(写入文件)后不保留对它的引用,则它不再被引用并且 java 足够智能以处理内存。

因此,为了使您的示例按预期工作,您需要保持对线程的引用。例如:

class MainClass {
public static void main(String[] args) {
List<B> objects=new ArrayList<>();
while(true){
objects.add(new B());
}
}
}

class B implements Runnable {
@Override
public void run() {
//do nothing
}
}

理论上对象创建没有限制。实际上,根据堆大小存在限制。堆是JVM分配的内存区域,用来存放对象。这就是为什么当您的程序用完内存(堆)时,您会面临 OutOfMemoryError。

关于java - Java 中对象实例的上限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51596083/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com