-2

我通过 SOOT-ECLIPSE 插件设置一个类作为主类,并希望它像单例一样运行。但是我的实现似乎不起作用,因为每次运行我都会得到不同的实例。

我尝试使用包装器并从那里调用单例类,以避免此类被 soot 的类加载器垃圾收集的情况。但我也有不同的情况。

我确认它在一个 JVM 上运行,因为每次运行时我得到的 PID 与每次运行时更改的类的实例是相同的。

我真的很感激对此的任何见解。

public class MyMain{

    private static boolean isFirstInstance = true;

    private static class MyMainHolder {
        private static final MyMain INSTANCE = new MyMain();
    }

    public static synchronized MyMain getInstance() {
        return MyMainHolder.INSTANCE;
    }

    private MyMain() {
        if (MyMainHolder.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }


    public static void main(String[] args) {
    System.out.println("PID: " + ManagementFactory.getRuntimeMXBean().getName());

    MyMain tmp = getInstance();
    }
4

2 回答 2

5

(来自评论...)

我的意思是我想运行这个类并每次都获得相同的实例。

听起来您对单例是什么有误解。如果您运行您的应用程序两次,即

$ java MyApp
[output]

$ java MyApp
[output]

那么这些是完全独立的 JVM 调用。当第一次运行完成时,不再有实例- JVM 分配的所有内存都将被释放。

如果您需要一个持久对象(即,即使 Java 没有运行,它仍然存在于某处),那么这是一个非常不同的场景,您应该研究序列化 - 尽管您仍然不应该期望两个应用程序在不同的实例上运行JVM 在内存中看到相同的对象。

编辑:现在我们知道你在 Soot 下运行,有可能每次都创建一个单独的类加载器,所以你会得到一个不同的实例。从根本上说,您需要了解代码运行的上下文,并在问题中提供该信息(以及您正在观察的确切内容)。

于 2014-07-04T15:14:38.680 回答
1

看来,OP 实际上希望能够区分程序的第一次运行和后续运行。这将做到这一点:

public static void main(String[] args) {
    File file = new File("has_been_run");
    if (!file.exists()) {
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // first time
    } else {
        // subsequent times
    }
}

显然,文件是否以某种方式被删除,然后再次算作“第一次运行”。

所以可以对任何可用的持久数据存储做类似的事情。

于 2014-07-04T15:11:33.933 回答