我们构建了一个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属性是否安全?因为我们正在修改它,它可以在线程之间变异吗?
任何反馈都将非常感谢。提前谢谢。
答案 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
...