Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Double.valueOf

Tags:

java

jvm

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 :D

  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?

like image 371
fabiitch Avatar asked Jul 14 '20 17:07

fabiitch


People also ask

What is double valueOf () in Java?

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 .

What does double parseDouble mean in Java?

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 .

What is the difference between double valueOf and double parseDouble?

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.


Video Answer


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

like image 118
apangin Avatar answered Sep 20 '22 02:09

apangin