Clojure

read/print handlers for inst/java.util.Date inconsistent between different JDKs

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Patch:
    Code

Description

Problem
The default REPL printing and reading wrt Dates is inconsistent between a minimal runtime environment (like a JVM with only the java.base module, or the deprecated JDK8 bootclasspath/bcp) and a full JVM.

There are a handful of references in Clojure to classes that live outside of the java.base module (or bcp). In such all places the referent class does not load automatically during Clojure's init. (They are loaded on demand, e.g. when the user first calls bean) The load of the core.instant namespace became conditional in Clojure 1.9, depending on the availability of the java.sql.Timestamp class. This was an accommodation made to enable lein to Clojure to run on the Java 8 bootclasspath, which lein used as a hack to avoid bytecode verification and thus load faster. (The reference to java.sql.Timestamp was verboten on the bcp) This also had the by-product of not loading read/print handlers for java.util.Date, which do exist on the bcp or java.base module.

present situation

  • lein has meanwhile stopped (mis)using the bootclasspath (instead skipping bytecode verification explicitly)
  • The notion of a bootclasspath no longer exists as of JDK9
  • There is now a bottom module with a clearly-defined set of classes, including java.util.Date and java.time.Instant
  • jlinking JVMs is a common and effective container deployment strategy

Clojure already runs fine on the bootclasspath or a JVM with only #{java.base}, but because the default data reader & clojure.instant aren't loaded, no read/print handlers for inst/j.u.Date get installed. The conditional load is about java.sql.Timestamp, which is never in default use anyways (besides the print handler) but it affects things that work fine in a reduced environment. (java.sql.Timestamp is in the java.sql module, which adds an additional 12MB to a jlinked jvm)

Great tagged value handling for dates sets Clojure's REPL apart from other dynlangs. It would be nice to have those conveniences available consistently on all modularized JDKs.

considerations
reduce the scope of the conditional load to avoid affecting date read/print handlers?
move the install of the read handler into clojure.instant, and load it unconditionally? (There was never a promise about when the handler was installed)
java.time.Instant is also in the bootclasspath or java.base module

informational
The following is a list of class references outside of the java.base module, not including the check for java.sql.Timestamp inside core.clj

non java.base references
clojure.core$bean                                  -> java.beans.BeanInfo                                java.desktop
   clojure.core$bean$fn__6987$fn__6988                -> java.beans.PropertyDescriptor                      java.desktop
   clojure.core$resultset_seq                         -> java.sql.ResultSet                                 java.sql
   clojure.inspector$inspect                          -> java.awt.BorderLayout                              java.desktop
   clojure.inspector$inspect_table                    -> java.awt.Component                                 java.desktop
   clojure.inspector$inspect_tree                     -> java.awt.Component                                 java.desktop
   clojure.instant$construct_timestamp                -> java.sql.Timestamp                                 java.sql
   clojure.instant$print_timestamp                    -> java.sql.Timestamp                                 java.sql
   clojure.java.browse_ui$open_url_in_swing           -> java.awt.Component                                 java.desktop
   clojure.lang.XMLHandler                            -> org.xml.sax.Attributes                             java.xml
   clojure.repl$set_break_handler_BANG_               -> sun.misc.Signal                                    JDK internal API (jdk.unsupported)
   clojure.repl$set_break_handler_BANG_               -> sun.misc.SignalHandler                             JDK internal API (jdk.unsupported)
   clojure.repl.proxy$java.lang.Object$SignalHandler$d8c00ec7 -> sun.misc.Signal                                    JDK internal API (jdk.unsupported)
   clojure.repl.proxy$java.lang.Object$SignalHandler$d8c00ec7 -> sun.misc.SignalHandler                             JDK internal API (jdk.unsupported)
   clojure.xml$startparse_sax                         -> javax.xml.parsers.SAXParserFactory                 java.xml
   clojure.xml$fn__8900                               -> org.xml.sax.ContentHandler                         java.xml

Activity

Hide
Ghadi Shayban added a comment -

approach in the patch

  • load clojure.instant unconditionally, as well as the #inst reader
  • wrap only the sql.Timestamp print-method extensions with a conditional load
  • remove when-class (now unused, it will not work for wrapping the defmethods because the java.sql.Timestamp class constants need to be delayed)
Show
Ghadi Shayban added a comment - approach in the patch
  • load clojure.instant unconditionally, as well as the #inst reader
  • wrap only the sql.Timestamp print-method extensions with a conditional load
  • remove when-class (now unused, it will not work for wrapping the defmethods because the java.sql.Timestamp class constants need to be delayed)

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated: