DefaultLinkGenerator链接()方法中的Map属性是否安全?

时间:2014-10-09 14:17:02

标签: grails

我们构建了一个Grails(2.3.7)应用程序,我们将覆盖DefaultLinkGenerator类中的链接(Map attr,String encoding =' UTF-8')。我们这样做的原因是在整个应用程序中使用相同的URL,因为它是来自客户的业务需求。基本上在重写link()方法中,我们使用新的请求参数修改Map。

现在处于生产阶段,我们看到以下异常情况偶尔发生,我们无法在本地重现。

2014-09-29 01:04:06,257 StackTrace ERROR Full Stack Trace:
java.lang.ArrayIndexOutOfBoundsException: 3
at org.codehaus.groovy.grails.web.mapping.UrlCreatorCache$ReverseMappingKey.<init>(UrlCreatorCache.java:196)
at org.codehaus.groovy.grails.web.mapping.UrlCreatorCache.createKey(UrlCreatorCache.java:62)
at org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingsHolder.getReverseMappingNoDefault(DefaultUrlMappingsHolder.java:265)
at org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingsHolder.getReverseMappingNoDefault(DefaultUrlMappingsHolder.java:257)
at org.codehaus.groovy.grails.web.mapping.DefaultLinkGenerator.link(DefaultLinkGenerator.groovy:213)
at gov.texas.multitenant.core.mapping.MultitenantLinkGenerator.super$2$link(MultitenantLinkGenerator.groovy) 

&#39; UrlCreatorCache $ ReverseMappingKey&#39;中的代码抛出上面的ArrayIndexOutOfException只有在循环期间Map属性(params)变异时才会发生。该代码的摘录如下。

paramKeys = new String[params.size()];
paramValues = new String[params.size()];
int i = 0;
for (Map.Entry entry : params.entrySet()) {
    **paramKeys[i] = String.valueOf(entry.getKey());** //throws exception here
    String value = null;
    if (entry.getValue() instanceof CharSequence) {
        value = String.valueOf(entry.getValue());
    }
    ...
    paramValues[i] = value;
    i++;
}

现在我的问题是,这个Map属性是否安全?因为我们正在修改它,它可以在线程之间变异吗?

任何反馈都将非常感谢。提前谢谢。

1 个答案:

答案 0 :(得分:0)

你不会在那个方法中知道 - 任何实现Map接口的东西都是允许的。但这并不重要 - 你造成了这个问题(作为一个看似非线程安全的实例的两个并发编辑器之一)并且可以很容易地修复它。

不是修改地图,而是创建一个新地图(任何Map实现都会执行,因为只有您的代码和该方法中的代码可以访问它)并修改它,并将其传递给链接生成。然后扔掉它并使用真实地图进行进一步计算。像

这样的东西
def attrs = ... // the 'real' map
def copy = [:] + attrs
copy.foo = 42
copy.bar = 'a very high one indeed'

String link = linkGenerator.link(copy)
// 
...

def foo = attrs.foo // not available, set in copy, but no longer using that
...