Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by

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

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

2 Answers

0 votes
by

Comment made by: gshayban

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)
0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-2380 (reported by gshayban)
...