[Bug 235018] java/openjdk8: adding millisecond resolution to get/setLastModified breaks many apps

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Thu Jan 17 17:44:24 UTC 2019


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235018

--- Comment #3 from aryeh.friedman at gmail.com ---
Java 8 != Java 11 

Java makes the absolute guarantee that if you compile for one language spec
version it will work on all JVM's on all platforms of the same language spec
version.  Changing the granularity of a method fundamentally breaks that
promise.  The original source for OpenJDK8 is 1 second resolution and people do
count on that.

Additionally RFC 7231 section 7.1.1.1 (as "imported" from RFC 5322, the
provided EBNF does not include sub-second resolutions) specifies only second
resolution it makes no provisions for having/not having sub-second resolutions
(i.e. that is undefined behavior which again violates Java's portability
promise if a specific JVM on a specific platform [OpenJDK 8 on FreeBSD] decides
to arbitrarily change how one of the standard library's computes/returns
values).

The way it can break a tomcat-based web app is that one of the practices used
in some REST-like API's (such as the one that triggered this bug report) is
that when a PUT/POST is made it is required to be proceeded by a GET, and then
the PUT/POST request contains an If-Unmodified-Since header echoing back the
Last-Modified header of the response to proceeding GET, to help minimize
concurrent update issues, consistent with RFC-based standards.   The server's
processing of the PUT/POST then involves comparing the re-sent header to the
actual file modification time.   Since the HTTP standard time format for these
headers is second resolution but the Java 11 (but NOT Java 8) standard library
one is millisecond resolution, they almost never agree and therefore the
PUT/POST is rejected as being out of date.

In a tomcat-based web app using Java 11, this problem could be solved by
rounding down the time to a one-second resolution.  However, this step should
not be necessary in a Java 8 application, because of Java's portability promise
within any given language spec version.

Here is the specific line that fails:

if ( ! ifUnmodifiedSinceTime.equals(lastModifiedTime) )
                        throw new HResVersionConflictException(
                                   "Write conflict:  Up-to-date"
                                           + " If-Unmodified-Since"
                                           + " timestamp must be"
                                           + " obtained, as"
                                           + " Last-Modified"
                                           + " timestamp metadata,"
                                           + " via GET "
                                           + writeID.toUrlPath(
                                                      pathPrefix));

As proven by following debugging output:

-----------------------------------
MethodProcUtil.checkWriteConflict:
  -- ifUnmodifiedSinceTime = 1547742518000 | Thu Jan 17 11:28:38 EST 2019
  -- lastModifiedTime = 1547742518769 | Thu Jan 17 11:28:38 EST 2019
-----------------------------------

Here is the same debugging output from a pre-patch openjdk 8 on same version of
FreeBSD (identical VM's running on the same host machine except that one VM
uses the post-patch openjdk and the other VM uses pre-patched):

-----------------------------------
MethodProcUtil.checkWriteConflict:
  -- ifUnmodifiedSinceTime = 1546916804000 | Mon Jan 07 22:06:44 EST 2019
  -- lastModifiedTime = 1546916804000 | Mon Jan 07 22:06:44 EST 2019
-----------------------------------

Other factors being equal, millisecond resolution would, of course, be better
than second resolution.  But the move to millisecond resolution should not
break existing applications that depend on a particular version of Java.

If, for whatever reason, it is deemed necessary to take such a radical step as
to make such an improvement without waiting for the appropriate version of
Java, then any such change should AT LEAST be documented MUCH, MUCH more
conspicuously than this one was.  (I found no documentation of this change at
all except for a comment within the commit.)

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-java mailing list