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 :D
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?
ValueOf(Double) Returns a Double instance representing the specified double value. ValueOf(String) Returns a Double object holding the double value represented by the argument string s .
parseDouble. public static double parseDouble(String s) throws NumberFormatException. Returns a new double initialized to the value represented by the specified String , as performed by the valueOf method of class Double .
valueOf() creates a Double object which is often not needed. parseDouble() does not. With autoboxing it's valueOf(String) which is no longer needed, but is therefore backward compatibility.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With