如果匿名对象使用外部方法无穷大的局部变量,它是否可能是堆栈溢出的?

问题描述

我对Java中的匿名对象有疑问。

如果我创建一个具有一个匿名对象的静态方法name = go()),并且该匿名对象使用go()的局部变量。

我知道用于匿名对象的局部变量必须声明为final

然后在堆栈区域而不是堆区域中创建final variable(numberCnt)

堆栈区域不是GC的目标。

如果我无限地调用go(),是否会发生堆栈溢出?

以下是我的问题来源。

package com;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestMain {
    public static void main(String[] args) {

        int i =0;

        while(true) {
            i++;
            go(i);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }

            if(i > 10_000_000) {
                i=0;
            }
        }
    }

    private static void go(int i) {

        int numberCnt = i;

        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                String rtnValue = "Number=>" + numberCnt;

                System.out.println("Number=>" + rtnValue);

                return rtnValue;
            };
        };

        ExecutorService executorService = Executors.newFixedThreadPool(4);

        executorService.submit(callable);
    }
}

解决方法

匿名类复制在创建匿名类对象时捕获的变量的值。因此,基本上,您的匿名类具有一个用于捕获int的隐藏numberCnt实例变量,并且您可以想象,在后台,编译器基本上将numberCnt传递给隐藏的“构造函数”您的匿名类来初始化此隐藏的实例变量。函数返回时,go的堆栈帧消失了,并且堆栈上go的堆栈帧不超过1个。您只会在堆上得到很多匿名类的实例,并且每个实例都有一个int实例变量,其值不同。