Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix concurrency issues in XStreamMarshaller
Prior to this commit, if an instance of XStreamMarshaller was used concurrently from multiple threads without having first invoked the afterPropertiesSet() method, the private `xstream` field could be initialized multiple times resulting in a ConcurrentModificationException in XStream's internal DefaultConverterLookup. This commit fixes these concurrency issues by making the `xstream` field volatile and by implementing a double-checked locking algorithm in getXStream() to avoid concurrent instance creation. Closes gh-25017
- Loading branch information
Showing
2 changed files
with
33 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright 2002-2018 the original author or authors. | ||
* Copyright 2002-2020 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
|
@@ -113,6 +113,7 @@ | |
* @author Peter Meijer | ||
* @author Arjen Poutsma | ||
* @author Juergen Hoeller | ||
* @author Sam Brannen | ||
* @since 3.0 | ||
*/ | ||
public class XStreamMarshaller extends AbstractMarshaller implements BeanClassLoaderAware, InitializingBean { | ||
|
@@ -187,7 +188,7 @@ public class XStreamMarshaller extends AbstractMarshaller implements BeanClassLo | |
private ClassLoader beanClassLoader = new CompositeClassLoader(); | ||
|
||
@Nullable | ||
private XStream xstream; | ||
private volatile XStream xstream; | ||
|
||
|
||
/** | ||
|
@@ -616,12 +617,21 @@ protected void customizeXStream(XStream xstream) { | |
* <p><b>NOTE: This method has been marked as final as of Spring 4.0.</b> | ||
* It can be used to access the fully configured XStream for marshalling | ||
* but not configuration purposes anymore. | ||
* <p>As of Spring Framework 5.2.7, creation of the {@link XStream} instance | ||
* returned by this method is thread safe. | ||
*/ | ||
public final XStream getXStream() { | ||
if (this.xstream == null) { | ||
this.xstream = buildXStream(); | ||
XStream xs = this.xstream; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
sbrannen
Author
Member
|
||
if (xs == null) { | ||
synchronized (this) { | ||
xs = this.xstream; | ||
if (xs == null) { | ||
xs = buildXStream(); | ||
this.xstream = xs; | ||
} | ||
} | ||
} | ||
return this.xstream; | ||
return xs; | ||
} | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Can we use
SingletonSupplier
to eliminate boilerplate code?