查看grafana发现,heap上来了,并且很长时间都下不去,dump了一下线程,并使用eclipse mat查看。发现有很多的HashMap对象。

原因如下。

项目中使用了

public static String getBrowser(String ua) {
    UserAgentAnalyzer userAgentAnalyzer = UserAgentAnalyzer
            .newBuilder()
            .hideMatcherLoadStats()
            .withCache(10000)
            .withField(UserAgent.AGENT_NAME_VERSION)
            .build();
    UserAgent.ImmutableUserAgent userAgent = userAgentAnalyzer.parse(ua);
    return userAgent.get(UserAgent.AGENT_NAME_VERSION).getValue();
}

刚开始以为是这个10000的问题,尝试把10000修改为0,发现问题依旧,说明并不是这个10000的问题。

追踪代码,调用到了

// nl.basjes.parse.useragent.AbstractUserAgentAnalyzer#parse
public synchronized ImmutableUserAgent parse(MutableUserAgent userAgent) {
    if (userAgent == null) {
        return null;
    }
    if (parseCache == null) {
        userAgent.reset();
        return super.parse(userAgent);
    }
    String             userAgentString = userAgent.getUserAgentString();
    ImmutableUserAgent cachedValue     = parseCache.get(userAgentString);
    if (cachedValue != null) {
        return cachedValue; // As it is immutable it can safely be returned as is
    } else {
        cachedValue = super.parse(userAgent);
        parseCache.put(userAgentString, cachedValue);
    }
    // We have our answer.
    return cachedValue;
}

其中使用到了parseCache对象

public static final int DEFAULT_PARSE_CACHE_SIZE = 10000;
protected int cacheSize = DEFAULT_PARSE_CACHE_SIZE;


private synchronized void initializeCache() {
    if (cacheSize >= 1) {
        parseCache = new LRUMap<>(cacheSize);
    } else {
        parseCache = null;
    }
}

并且cacheSize很大,且一直保存在内存中。

排查后发现这里只是获取客户端浏览器信息,但是并没有页面要显示。

  • 换一个轻量级的解析库。
  • 删除getBrowser()方法及pom。
  • AbstractUserAgentAnalyzer中有disableCache()方法。

我们采取了第二条。

pom.xml中依赖如下。

<!-- 解析客户端操作系统、浏览器信息 -->
<dependency>
    <groupId>nl.basjes.parse.useragent</groupId>
    <artifactId>yauaa</artifactId>
    <version>5.23</version>
</dependency>
作者:张三  创建时间:2025-10-14 09:58
最后编辑:张三  更新时间:2025-10-14 10:01