Java 中对象实例的上限
Cap for Object instances in Java
我正在试验对象实例,因为我想查明单个 Java 进程是否定义了最大数量的对象实例。所以我简单地创建了一个对象,它从构造函数中递归地调用自己,如下所示:
public class A{
private A a;
public A(){
a = new A();
}
}
和一个主要 class 像这样:
public class random {
public static void main(String[] args) {
A a = new A();
}
}
这显然导致了堆栈溢出异常。谷歌搜索后,我发现每个 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();
}
}
}
像这样 运行nable:
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 运行 所在的线程会简单地溢出。所以我决定将计数写入文件,每个线程一个文件。
我的 classes 现在看起来像这样:
主要:
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
的引用,我创建的任何实例都被我的主 class 间接引用。所以我认为垃圾收集器不会触及我宝贵的实例(对吧?)。我的 RAM 怎么没有完全填满?或者至少 JVM 如何没有达到其分配的 RAM 限制?如果我相信我的计数器我有超过 1600 万个对象实例,甚至不计算 B
的实例,并且如果我允许的话,它会每秒创建 83.000 个以上的对象引用 继续。
此外,当我们讨论这个问题时:一个简单的对象会占用多少 RAM?我知道它显然与对象中引用和使用的变量和数量有关,但我们只说一个完全空的对象。它会使用多少内存?
PS:我知道我可以通过在我的主 class 中同时启动线程来加速我的程序,但我的(主要)意图不是用完我所有的磁盘 space 尽可能快,但要计算对象实例:)
我认为你的测试的问题是你的对象仍然被垃圾收集。如果您创建一个线程并且在它完成工作(写入文件)后不保留对它的引用,则它不再被引用并且 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 进程是否定义了最大数量的对象实例。所以我简单地创建了一个对象,它从构造函数中递归地调用自己,如下所示:
public class A{
private A a;
public A(){
a = new A();
}
}
和一个主要 class 像这样:
public class random {
public static void main(String[] args) {
A a = new A();
}
}
这显然导致了堆栈溢出异常。谷歌搜索后,我发现每个 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();
}
}
}
像这样 运行nable:
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 运行 所在的线程会简单地溢出。所以我决定将计数写入文件,每个线程一个文件。
我的 classes 现在看起来像这样:
主要:
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
的引用,我创建的任何实例都被我的主 class 间接引用。所以我认为垃圾收集器不会触及我宝贵的实例(对吧?)。我的 RAM 怎么没有完全填满?或者至少 JVM 如何没有达到其分配的 RAM 限制?如果我相信我的计数器我有超过 1600 万个对象实例,甚至不计算 B
的实例,并且如果我允许的话,它会每秒创建 83.000 个以上的对象引用 继续。
此外,当我们讨论这个问题时:一个简单的对象会占用多少 RAM?我知道它显然与对象中引用和使用的变量和数量有关,但我们只说一个完全空的对象。它会使用多少内存?
PS:我知道我可以通过在我的主 class 中同时启动线程来加速我的程序,但我的(主要)意图不是用完我所有的磁盘 space 尽可能快,但要计算对象实例:)
我认为你的测试的问题是你的对象仍然被垃圾收集。如果您创建一个线程并且在它完成工作(写入文件)后不保留对它的引用,则它不再被引用并且 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。