我快速浏览了Guava源代码和文档,似乎都没有提及版本。我想知道是否有办法在运行时获得Guava的版本信息。
如果实际上没有这样的东西,则不必通过任何getter访问此版本信息;如果它藏在某个地方,而某个地方在加载番石榴时没有得到GC,那就足够了。
此版本信息是否在运行时可用?
我有一个非常具体的用途。我的工作很大一部分是分析Java堆转储,以识别和修复代码中导致内存使用过高的地方。对于此任务,我使用fasthat,这是jhat的经过大量修改的版本,其中包含对我的工作有用的特殊功能。
其中一项功能是显示容器的内容。我已经为ArrayList
,HashMap
,ConcurrentHashMap
等类似实现了这一点。(我根据我在堆转储中遇到的情况,按需实现类型打印机。)目前,我正在为Guava的CustomConcurrentHashMap
实现一台打印机。
由于结构的布局可以在不同版本之间进行更改,因此我的代码会根据正在使用的版本调整其解包行为。例如,在工作中,我们曾经使用JRuby 1.2,但最近切换到JRuby 1.6,因此我为这两个版本都有类型打印机,并根据它在堆转储中找到的版本信息选择版本。
所以,这就是问题第二段的要点:如果版本信息在堆转储中的任何地方,那就是我所需要的。
并且在有人要求之前:堆转储数据不是“实时”,因此您不能简单地调用toString
等。你真的必须走数据结构来提取出来,你真的必须使用实现细节到第n度。; - )
答案 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