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

Chr*_*ung 11 java guava

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

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

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


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

其中一个功能是显示容器的内容.我已经为这样的人实现了这个ArrayList,HashMap,ConcurrentHashMap,等(我的需求实现类型的打印机,基于我在我们的堆转储遇到的问题.)目前,我执行番石榴的一个类型的打印机CustomConcurrentHashMap.

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

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

在任何人问之前:堆转储数据不是"实时",所以你不能简单地打电话toString等.你真的必须走数据结构来提取出来,你真的必须使用实现细节到第n度.;-)

Eti*_*veu 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...");
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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