...
Method
...
chaining
...
is
...
a
...
convenience
...
mechanism
...
that
...
allows
...
multiple
...
method
...
invocations
...
on
...
the
...
same
...
object
...
to
...
occur
...
in
...
a
...
single
...
statement.
...
Classes
...
that
...
support
...
method
...
chaining
...
provide
...
several
...
setter
...
methods
...
that
...
return
...
the
...
this
...
reference.
...
Method
...
chaining
...
should
...
not
...
be
...
used
...
in
...
a
...
multithreaded
...
environment
...
because
...
chained
...
invocations
...
of
...
a
...
set
...
of
...
methods
...
are
...
non-atomic
...
and,
...
consequently,
...
noncompliant
...
with
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
Noncompliant Code Example
Method chaining is useful for building an object and setting its optional fields. However, in a multithreaded environment, a thread may observe a shared field to contain inconsistent values. This noncompliant code example shows the Javabeans pattern which is not safe for multithreaded use.
Code Block | ||
---|---|---|
| ||
]. h2. Noncompliant Code Example Method chaining is useful for building an object and setting its optional fields. However, in a multithreaded environment, a thread may observe a shared field to contain inconsistent values. This noncompliant code example shows the Javabeans pattern which is not safe for multithreaded use. {code:bgColor=#FFcccc} final class USCurrency { // Change requested, denomination (optional fields) private int quarters = 0; private int dimes = 0; private int nickels = 0; private int pennies = 0; public USCurrency() {} // Setter methods public USCurrency setQuarters(int quantity) { quarters = quantity; return this; } public USCurrency setDimes(int quantity) { dimes = quantity; return this; } public USCurrency setNickels(int quantity) { nickels = quantity; return this; } public USCurrency setPennies(int quantity) { pennies = quantity; return this; } } // Client code: private final USCurrency currency = new USCurrency(); // ... new Thread(new Runnable() { @Override public void run() { currency.setQuarters(1).setDimes(1); } }).start(); new Thread(new Runnable() { @Override public void run() { currency.setQuarters(2).setDimes(2); } }).start(); {code} |
The
...
Javabeans
...
pattern
...
uses
...
a
...
no-argument
...
constructor
...
and
...
a
...
series
...
of
...
parallel
...
setter
...
methods
...
to
...
build
...
an
...
object.
...
This
...
pattern
...
is
...
not
...
thread-safe
...
and
...
can
...
lead
...
to
...
inconsistent
...
object
...
state.
...
In
...
this
...
example,
...
a
...
client
...
that
...
constructs
...
a
...
USCurrency
...
object
...
and
...
starts
...
two
...
threads
...
as
...
shown
...
may
...
find
...
the
...
object
...
to
...
contain
...
two
...
quarters
...
and
...
one
...
dime
...
or
...
one
...
quarter
...
and
...
two
...
dimes,
...
contrary
...
to
...
what
...
it
...
expects.
...
Compliant Solution
Wiki Markup |
---|
This compliant solution uses the variant of the Builder pattern \[[Gamma 95|AA. Java References#Gamma 95]\] suggested by Bloch \[[Bloch 08|AA. Java References#Bloch 08]\] to ensure thread safety and atomicity of object creation. |
Code Block | ||||
---|---|---|---|---|
| =
| |||
} final class USCurrency { private final int quarters; private final int dimes; private final int nickels; private final int pennies; public USCurrency(Builder builder) { this.quarters = builder.quarters; this.dimes = builder.dimes; this.nickels = builder.nickels; this.pennies = builder.pennies; } // Static class member public static class Builder { private int quarters = 0; private int dimes = 0; private int nickels = 0; private int pennies = 0; private Builder() {} // Setter methods public Builder setQuarters(int quantity) { this.quarters = quantity; return this; } public Builder setDimes(int quantity) { this.dimes = quantity; return this; } public Builder setNickels(int quantity) { this.nickels = quantity; return this; } public Builder setPennies(int quantity) { this.pennies = quantity; return this; } public USCurrency build() { return new USCurrency(this); } } public static public Builder GetBuildernewInstance() { return new Builder(); } } } // Client code: private volatile USCurrency currency; // ... new Thread(new Runnable() { @Override public void run() { Foo.this.currency = USCurrency.GetBuilderBuilder.newInstance().setQuarters(1).setDimes(1).build(); } }).start(); new Thread(new Runnable() { @Override public void run() { Foo.this.currency = USCurrency.Builder.GetBuildernewInstance().setQuarters(2).setDimes(2).build(); } }).start(); {code} The {{GetBuilder()}} factory is called with the _required_ arguments (if any) to obtain a {{Builder}} object. The _optional_ parameters are set using the setter methods of the builder. The object construction concludes with the invocation of the {{build()}} method. This also makes the class {{Currency}} immutable, and consequently, thread-safe. Note that the {{currency}} field cannot be declared as final because it is set to a new immutable object from the threads. It is declared as volatile in compliance with [CON09-J. Ensure visibility of shared references to immutable objects]. If input needs to be validated, ensure that the values are defensively copied prior to the validation (see [FIO00-J. Defensively copy mutable inputs and mutable internal components] for more information). The builder class does not violate [SCP03-J. Do not expose sensitive private members of the outer class from within a nested class] because it maintains a copy of the variables defined in the scope of the containing class. These take precedence and as a result, do not break encapsulation. h2. Exceptions *EX1*: A class may use method chaining in a multithreaded environment if it sufficiently documents this fact. Client code must externally use some locking to ensure that the method calls are thread-safe. {mc} I don't think this class is necessary. (to avoid bloat; most readers would know what we are talking about by now) {code:bgColor=#ccccff} // This class is not thread-safe. A client must provide locking on any // USCurrency object in a multi-threaded environment. final class USCurrency { // Change requested, denomination (optional fields) private int quarters = 0; private int dimes = 0; private int nickels = 0; private int pennies = 0; public USCurrency() {} // Setter methods public USCurrency setQuarters(int quantity) { quarters = quantity; return this; } public USCurrency setDimes(int quantity) { dimes = quantity; return this; } public USCurrency setNickels(int quantity) { nickels = quantity; return this; } public USCurrency setPennies(int quantity) { pennies = quantity; return this; } } // ... // Client code: final USCurrency currency = new USCurrency(); final Object lock = new Object(); new Thread(new Runnable() { public void run() { synchronized (lock) { currency.setQuarters(1).setDimes(1); } } }).start(); new Thread(new Runnable() { public void run() { synchronized (lock) { currency.setQuarters(2).setDimes(2); } } }).start(); {code} This code achieves thread-safety by having the client code perform all modification of the {{USCurrency}} object only while a {{lock}} is held. {mc} h2. Risk Assessment Using method chaining in multithreaded environments without performing external locking can lead to non-deterministic behavior. || Rule || Severity || Likelihood || Remediation Cost || Priority || Level || | CON30- J | low | probable | medium | {color:green}{*}P4{*}{color} | {color:green}{*}L3{*}{color} | h3. Automated Detection TODO h3. Related Vulnerabilities Search for vulnerabilities resulting from the violation of this rule on the [CERT website|https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+FIO38-J]. h2. References |
The Builder.newInstance()
factory method is called with the required arguments (if any) to obtain a Builder
object. The optional parameters are set using the setter methods of the builder. The object construction concludes with the invocation of the build()
method. This also makes the class Currency
immutable, and consequently, thread-safe.
Note that the currency
field cannot be declared as final because it is set to a new immutable object from the threads. It is declared as volatile in compliance with CON09-J. Ensure visibility of shared references to immutable objects.
If input needs to be validated, ensure that the values are defensively copied prior to the validation (see FIO00-J. Defensively copy mutable inputs and mutable internal components for more information). The builder class does not violate SCP03-J. Do not expose sensitive private members of the outer class from within a nested class because it maintains a copy of the variables defined in the scope of the containing class. These take precedence and as a result, do not break encapsulation.
Exceptions
EX1: A class may use method chaining in a multithreaded environment if it sufficiently documents this fact. Client code must externally use some locking to ensure that the method calls are thread-safe.
Risk Assessment
Using method chaining in multithreaded environments without performing external locking can lead to non-deterministic behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
CON30- J | low | probable | medium | P4 | L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[API 06|AA. Java References#API 06]\]
\[[Bloch 08|AA. Java References#Bloch 08]\] Item 2: "Consider a builder when faced with many constructor parameters" |
...
...
...
...
...
...
...
...
...
...
...