TransWikia.com

Java Double.valueOf

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 Doubles 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 😀

  1. JVM intercept Double.valueOf() for call this box method?

  2. Double.valueOf doesn’t use JDK source and dont do a new Double()?

  3. The comment on Double.valueOf() is just a dump copy/paste, Double.valueOf and new Double have same effect?

2 Answers

  1. 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.

  2. 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.

  3. 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

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP