Stack Overflow Asked by fabiitch on November 4, 2021
At my work, all developer use Double.valueOf
instead of new Double
constructor. In every case. For Integer or Short I can understand it for cache values but for not for double
and float
.
I look Double.valueOf in OpenJDK sources :
/**
* Returns a {@code Double} instance representing the specified
* {@code double} value.
* If a new {@code Double} instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Double(double)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param d a double value.
* @return a {@code Double} instance representing {@code d}.
* @since 1.5
*/
public static Double valueOf(double d) {
return new Double(d);
}
So it just calls Double
s constructor.
I can understand why the method exist for be coherent with Integer/Short…
But the comment on the method:
this method should generally be used in preference to the constructor
After i see its the same comment on every valueOf()
method. (Integer,Short …)
The comment is false? Or an other process meddle?
I heard about intrinsic methods in Java, next step was search in hotspot code and in vmSymbol.hpp
/* boxing methods: */
do_name( valueOf_name, "valueOf")
do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S)
do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;")
do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S)
do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;")
do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S)
do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;")
do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S)
do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;")
do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S)
do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;")
do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S)
do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;")
do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S)
do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;")
do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S)
do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;")
So after I grep Double.valueOf
in source and I found withebox.cpp
static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
}
and box method code :
template <typename T>
static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
ResourceMark rm(thread);
jclass clazz = env->FindClass(name->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
jmethodID methodID = env->GetStaticMethodID(clazz,
vmSymbols::valueOf_name()->as_C_string(),
sig->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
CHECK_JNI_EXCEPTION_(env, NULL);
return result;
}
and this code …
Ok, I’m not advanced yet. This method box() is really called in server mode?
3 questions for resume 😀
JVM intercept Double.valueOf()
for call this box method?
Double.valueOf
doesn’t use JDK source and dont do a new Double()
?
The comment on Double.valueOf()
is just a dump copy/paste, Double.valueOf
and new Double
have same effect?
Integer(int)
, Double(double)
and similar constructors are deprecated (yes, they are actually marked as @Deprecated
) since Java 9 as a part of JEP 277.
The deprecation comment tells that
The static factory
valueOf(double)
is generally a better choice, as it is likely to yield significantly better space and time performance.
Although OpenJDK currently does not cache boxed doubles, static factory method opens a path for future optimizations. If it is decided to improve autoboxing of doubles either in the JVM or in the class library, applications will automatically benefit from the optimization without any changes from user side.
Another reason is that Double.valueOf
is indeed an intrinsic method in HotSpot. The JVM knows about autoboxing methods, and uses this knowledge in EliminateAutoBox optimization.
There are two related optimizations: EliminateAllocations and EliminateAutoBox. Even though they are both provided by Escape Analysis and look similar, they are applied in slightly different contexts, so it may happen that one optimization works, when the other does not, or vice versa.
When autoboxing elimination succeeds, e.g. when JIT compiler discovers matching valueOf
and doubleValue
calls, and the object does not escape, the optimizer gets rid of both calls altogether.
BTW, the mentioned Whitebox code is irrelevant. It is not used other than for internal HotSpot testing purposes.
The project Valhalla, which is in active development now, leads to entire rethinking of primitive wrappers.
The current idea is to make int
, double
, etc. inline types, with Integer
and Double
their reference projections. As a migration step, Integer
and Double
will become sealed abstract classes, hence there will be no way to instantiate them via constructors.
So, consider deprecation of constructors as an intermediate step to the project Valhalla. By encouraging usage of factory methods, JDK developers clear a way for many optimizations they can do under the hood, including inlining Double
instances wherever is possible.
Answered by apangin on November 4, 2021
The short answer: Consistency.
It is a concept you should strive for when coding, because it reduces the chance of errors, and makes the code easier to read.
Besides, you never know what optimizations might be added at any time, so use the valueOf()
method unless you require a new Double
value (which is extremely rare). Just because it doesn't cache common values right now, doesn't mean it won't in the future, or in a different implementation.
That is a concept called future-proofing, which is also something you should strive for when coding.
Answered by Andreas on November 4, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP