有没有办法在运行时获取正在使用的Guava版本? [英] Is there a way to get, at runtime, the version of Guava in use?

查看:118
本文介绍了有没有办法在运行时获取正在使用的Guava版本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



如果没有这样的东西,这个版本信息不必通过任何getter访问实际存在;如果它藏在一个没有加载Guava的地方的某个地方,那就足够了。



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






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



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



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



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



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

解决方案

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



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



类似于:

  / ** 
*一个{@link Predicate},用于检查给定{@link HeapDump}
* /中是否存在类
公共类ClassExistsPredicate实现Predicate< String> {

私人最终HeapDump heapDump;

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

@Override
public boolean apply(String fullyQualifiedClassName){
//检查堆转储中是否存在给定的类
返回true;
}

}


公共枚举GuavaVersion {

R01,

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

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

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

/ **
* @return {@link Set}添加的类别名称,用于唯一标识前一个版本的此版本(不是
*必需< b> all< ; / b>类!)
* /
设置< 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)){
返回版本;
}
}

抛出新的RuntimeException(无法确定Guava版本......);
}

}

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



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

I did a quick grep of the Guava source and documentation, and neither seem to have any mention of versions. I was wondering if there was a way Guava's version information can be obtained at runtime.

This version information doesn't have to be accessible via any getter, if no such thing actually exists; if it's stashed in a field somewhere that doesn't get GC'd while Guava is loaded, that would be sufficient.

Is this version information available anywhere at runtime?


I have a very specific use for this. A big part of my work is analysing Java heap dumps to identify and fix places in the code that cause exorbitant memory usage. For this task, I use fasthat, a heavily-modified version of jhat with special features useful to my work.

One of those features is to display the contents of containers. I've already implemented this for the likes of ArrayList, HashMap, ConcurrentHashMap, etc. (I implement type printers on demand, based on what I encounter in our heap dumps.) Currently, I'm implementing a type printer for Guava's CustomConcurrentHashMap.

Since the layout of structures can change between versions, my code tweaks its unpacking behaviour based on what version is in use. For example, at work, we used to use JRuby 1.2, but recently switched to JRuby 1.6, so I have type printers for both of those versions, and it selects the version based on the version information it finds in the heap dump.

So, that's the point of the second paragraph of the question: if the version information is anywhere in the heap dump, that's all I need.

And before anyone asks: heap dump data is not "live", so you cannot simply call toString or the like. You really have to walk the data structures to extract the bits out, and you really do have to use implementation details to the nth degree. ;-)

解决方案

This is more of a workaround, but I guess you could do this if there is no simpler way of accessing the Guava version:

In most Guava releases, classes / fields / methods are added / removed. You could try to look for them in the heap dump, and, depending on their existence, determine the Guava version.

Something like:

/**
 * 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...");
    }

}

Obviously, you should cache the Guava version number, since the computation might be slow... The approach could be extended to consider added methods / fields.

This approach could work with other projects, too.

这篇关于有没有办法在运行时获取正在使用的Guava版本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆