有没有办法在运行时获取正在使用的Guava版本?

时间:2011-10-08 02:49:27

标签: java guava

我快速浏览了Guava源代码和文档,似乎都没有提及版本。我想知道是否有办法在运行时获得Guava的版本信息。

如果实际上没有这样的东西,则不必通过任何getter访问此版本信息;如果它藏在某个地方,而某个地方在加载番石榴时没有得到GC,那就足够了。

此版本信息是否在运行时可用?


我有一个非常具体的用途。我的工作很大一部分是分析Java堆转储,以识别和修复代码中导致内存使用过高的地方。对于此任务,我使用fasthat,这是jhat的经过大量修改的版本,其中包含对我的工作有用的特殊功能。

其中一项功能是显示容器的内容。我已经为ArrayListHashMapConcurrentHashMap等类似实现了这一点。(我根据我在堆转储中遇到的情况,按需实现类型打印机。)目前,我正在为Guava的CustomConcurrentHashMap实现一台打印机。

由于结构的布局可以在不同版本之间进行更改,因此我的代码会根据正在使用的版本调整其解包行为。例如,在工作中,我们曾经使用JRuby 1.2,但最近切换到JRuby 1.6,因此我为这两个版本都有类型打印机,并根据它在堆转储中找到的版本信息选择版本。

所以,这就是问题第二段的要点:如果版本信息在堆转储中的任何地方,那就是我所需要的。

并且在有人要求之前:堆转储数据不是“实时”,因此您不能简单地调用toString等。你真的必须走数据结构来提取出来,你真的必须使用实现细节到第n度。; - )

3 个答案:

答案 0 :(得分:4)

如果你想获得maven构建类的版本,你可以从类开始,找到它来自的jar并读取maven添加的元信息(例如版本)

如果版本在路径中,更简单的方法是查看类路径,从文件名中查找guava和您正在使用的版本。

对于堆转储,类路径位于System属性中。

答案 1 :(得分:3)

这是一种解决方法,但我想如果没有更简单的方法来访问Guava版本,你可以这样做:

在大多数Guava版本中,添加/删除了类/字段/方法。您可以尝试在堆转储中查找它们,并根据它们的存在确定Guava版本。

类似的东西:

/**
 * A {@link Predicate} that checks whether a class exists in the given {@link HeapDump}
 */
public class ClassExistsPredicate implements Predicate<String> {

    private final HeapDump heapDump;

    public ClassExistsPredicate(HeapDump heapDump) {
        this.heapDump = heapDump;
    }

    @Override
    public boolean apply(String fullyQualifiedClassName) {
        // checks whether the given class exists in the heap dump
        return true;
    }

}


public enum GuavaVersion {

    R01,

    R02 {
        @Override
        Set<String> getAddedClasses() {
            return ImmutableSet.of("com.google.common.base.Foo");
        }
    },

    R03 {
        @Override
        Set<String> getAddedClasses() {
            return ImmutableSet.of("com.google.common.collect.ForwardingFooIterator");
        }
    },

    R04 {
        @Override
        Set<String> getAddedClasses() {
            return ImmutableSet.of("com.google.common.collect.FooFoo2");
        }
    };

    /**
     * @return a {@link Set} of added class names that uniquely identify this version from the preceding one (not
     *         necessarily <b>all</b> classes!)
     */
    Set<String> getAddedClasses() {
        return ImmutableSet.of();
    }

    public static GuavaVersion getGuavaVersionFor(HeapDump heapDump) {
        ClassExistsPredicate classExists = new ClassExistsPredicate(heapDump);

        for (GuavaVersion version : Lists.reverse(Arrays.asList(GuavaVersion.values()))) {
            if (Iterables.all(version.getAddedClasses(), classExists)) {
                return version;
            }
        }

        throw new RuntimeException("Unable to determine Guava version...");
    }

}

显然,您应该缓存Guava版本号,因为计算可能很慢......可以扩展该方法以考虑添加的方法/字段。

这种方法也适用于其他项目。

答案 2 :(得分:2)

您可以从Guava的JAR清单中检索版本。

public static String getGuavaVersion() {
    try {
        File file = new File(Charsets.class.getProtectionDomain().getCodeSource().getLocation().toURI());
        try (JarFile jar = new JarFile(file)) {
            return jar.getManifest().getMainAttributes().getValue("Bundle-Version");
        }
    } catch (Exception ex) {
        throw new RuntimeException("Unable to get the version of Guava", ex);
    }
}

不幸的是,这仅适用于Guava 11+。 Guava 10及更早版本还没有OSGI捆绑包。

另一种选择是从pom.properties检索版本。这适用于旧版本的番石榴:https://gist.github.com/seanizer/8de050427f3f199cf8f085b2a3a2473e