8000 Release v0.1.2 · Project516/java-web · GitHub
[go: up one dir, main page]

Skip to content
8000

v0.1.2

Latest

Choose a tag to compare

@Project516 Project516 released this 07 Nov 23:30 FD81
3a23e22

Faster starts, a real image-mode JDK, warm library VMs, child processes, file watching, large files, less memory per VM, and compatibility fixes.

Upgrading

  • The JDK now ships as one file, jdk/image.jar, in place of jdk/<module>.jar and jdk/jdk.localedata.txt. A page that serves dist/ needs no change, but the server must still answer Range requests, now for jdk/image.jar.
  • The java-web command now runs dist/cli.js. dist/node.js and its exports are unchanged.
  • Node keeps boot snapshots in ~/.cache/java-web/snapshots (up to 16). Set JAVA_WEB_SNAPSHOT_DIR to move it, or to an empty value to turn snapshots off.

New

  • Child processes under Node: ProcessBuilder, Runtime.exec and ProcessHandle start and manage the host's programs, with pipes, pipelines, redirects, environment and working directories as on HotSpot. Starting java starts another java-web VM on the same image. (#45)
  • WatchService reports files created, changed and deleted inside the VM. (#46)
  • Files of any size: a file streams to the host once it passes 4 MiB instead of living in memory, so multi-GB files work under Node. A 256 MiB write and read went from 829 MB and 36 s to 338 MB and 2.9 s. (#47)
  • Warm snapshots, opt-in with warmSnapshot: true (startLibrary under Node, cheerpjInit in the browser): a library VM is saved again once its calls have warmed it up, so a later start skips javac's cold start. A first javac compile takes about a fifth of the time under Node and half in Chromium. The image also keeps the JIT's generated code, which makes the first call after a restore about 20% faster still. (#48, #58, #59)
  • cheerpjInit({ maxHeap: "256m" }) caps the whole Java heap in the browser, as -Xmx does under Node: a program that fills it gets OutOfMemoryError: Java heap space instead of the tab dying. (#57)
  • cheerpjInit({ debug: true }) logs VM events to the console, such as whether a warm snapshot was saved or restored. (#52)
  • jdk.management is in the image: com.sun.management.UnixOperatingSystemMXBean (open and maximum descriptor counts) and HotSpotDiagnosticMXBean.getVMOption. (#61)
  • Symbolic and hard links on host file systems, SecureDirectoryStream, and new files and directories created with the requested mode less the umask. (#61)
  • Deflater compresses: zlib's levels, strategies, flush modes and dictionaries. Level 6 output is within 0.1% of zlib's size, and a jar of 1,439 classes comes out 54% smaller. (#63)
  • ThreadMXBean thread info, thread dumps with locked monitors and synchronizers, and deadlock detection for monitors and java.util.concurrent locks, with no cost to synchronized or ReentrantLock. (#65)
  • Virtual threads no longer pin their carrier when they block on a monitor or wait in Object.wait, as in JDK 24 and later. (#68)
  • Launcher options: -m and --module, -Xbootclasspath/a (directories and jars, repeatable) and --patch-module for boot modules. bin/java exists in the image, and kill -QUIT prints a thread dump. (#69)
  • jdk.net and jdk.nio.mapmode are in the image. A TZ value that is a POSIX rule, such as MEZ-1MESZ,M3.5.0,M10.5.0/3, sets the default time zone's offset and daylight saving dates. Memory pools and managers have G1's names, as HotSpot's default collector reports them. (#69)

Faster

  • Boot snapshots: a VM starts from the state saved after an earlier boot with the same inputs. Hello world under Node goes from about 2.3 s to under 0.5 s. In the browser, later runs on a page start in about 0.3 s. (#29)
  • Image-mode JDK: the JDK is a jlinked lib/modules, as a normal JDK has, instead of an exploded tree. A full boot under Node drops from 1.9 s to 1.3 s, and jrt:/ no longer walks every file of the image. (#37)
  • javac's first compile is about 40% faster in Node (10.3 s to 6.0 s from a snapshot) and in the browser (6.2 s to 3.7 s on a cold page). (#34, #37)
  • Browser downloads: one request per app class instead of two, a smaller boot index, and the image ranges a start and javac read packed into boot.pack and jdk/javac.pack. (#30, #31, #37)
  • Node's compile cache for the java-web command, cheaper calls between compiled and interpreted code, and intrinsics for SHA, AES, BigInteger, Math.multiplyHigh and P-256 (EC work about 44% faster). (#20, #21, #26, #27, #28, #33)
  • Less heap per VM: UTF-8 constants are plain strings, parsed member records are dropped after linking, and the constant pool lives in typed arrays. Each saves a few MB; the constant pool change alone takes about 8 MB off a library VM after a javac compile. (#41, #55, #60)
  • Unmapping a file gives its memory back. (#56)
  • Zip reading and writing: faster inflate and CRC32, native array compare and hash code (which also speeds up Arrays.equals, Arrays.mismatch and String.hashCode), and calls that see one receiver class are inlined. A 12 MB deflated zipfs entry writes and verifies in 449 ms instead of 1,154 ms. (#62)
  • Uncontended synchronized is 12 to 38% faster, and contended monitors between platform threads about 30% faster. (#68)
  • Startup and memory: class file parts are decoded on first use, line tables point into the class bytes, and generated code is smaller. About 21% less heap after a javac compile (101 to 80 MB), and hello world from a boot snapshot about 13% faster. Snapshots from older builds are rebuilt once. (#70)

Fixes

  • Class initialization, exception handlers and bytecode edge cases now match HotSpot. (#22, #25)
  • Files: writes the host refuses are reported, a new file the host refuses reports the host's reason, renaming a file over a directory is refused, and special characters in browser file paths are kept. (#19, #23, #24, #35)
  • Modification times set to the nanosecond read back exactly. (#38)
  • FileStore and File.getTotalSpace(), getFreeSpace() and getUsableSpace() report the host file system's figures, and direct I/O (ExtendedOpenOption.DIRECT) works. (#42)
  • java.util.prefs stores preferences: the file natives behind Preferences.userRoot() are implemented. (#43)
  • A process that upgrades the package in place keeps each running VM on the image it started with. (#39)
  • The java-web command no longer hangs at exit on some x64 hosts after a program used several hundred MB. (#44)
  • A RandomAccessFile opened read-only refuses writes, as on HotSpot. (#47)
  • A thread that joins the main thread no longer deadlocks when main ends, for example with an uncaught exception. (#49)
  • Under Node, -Xmx caps the whole heap: a program that fills it gets OutOfMemoryError: Java heap space, which it can catch, instead of being killed. Before, it only capped a single array. (#50, #53)
  • Writing far past the end of a file, as sparse files do, no longer allocates the gap, so multi-GB files work. Append mode follows O_APPEND, and a directory can be opened read-only as a channel. (#54)
  • A file mapping that does not fit fails with IOException: Map failed, as on HotSpot, instead of crashing. (#56)
  • A warm or boot snapshot of a deep object graph (a long linked list, for example) no longer overflows the stack while saving or restoring. Older snapshot files are ignored and rebuilt. (#59)
  • An open file keeps its inode number after its path is deleted, child programs are found on the parent's PATH, and an unreadable file fails with EACCES. (#61)
  • jrt:/ reads class files, and stack frames carry module versions as on HotSpot. (#37)
  • Runtime reports real heap figures. (#26)
  • A VM that hits an internal error on its main thread exits with status 1 instead of hanging. (#29)
  • park, Object.wait and Thread.sleep with a timeout longer than about 24 days, such as LockSupport.parkNanos(Long.MAX_VALUE), no longer wake after 1 ms and spin. (#66)
  • -XX:OnOutOfMemoryError runs its commands and -XX:MaxDirectMemorySize limits direct buffers, as on HotSpot. java -version works. (#67)
  • File access times are kept and reported: reading a host file no longer changes its access time, and setting times on a symlink with NOFOLLOW_LINKS changes only the link. (#67)
  • WatchService sees changes other processes make in a watched host directory, and no longer hangs when a watched directory is deleted during registration or crashes on a long event queue. (#67, #72)
  • Sockets: a socket reports writable after shutdownOutput, a connected datagram socket can connect again, Unix domain sockets bind the unnamed address and long paths, and an accepted Unix socket reports its client's name. (#69)
  • Processes: a child's output is read in full before the VM hears it exited, merged output included; the PATH search and exec errors follow the JDK's; an unlimited open file limit reports -1. (#69, #72)
  • A stack overflow inside an overflow handler throws a bare StackOverflowError instead of failing the VM. The ConstantPool natives check their index and entry kind. (#69)
  • Deflater.setDictionary in the middle of a raw stream no longer drops input it had taken but not yet written. (#72)
  • An open file shares bytes with another open of the same path only when they are the same file, so reopening a replaced symlink target reads the new file. (#72)
  • An OutOfMemoryError is thrown even when the hook that reports it fails, and -XX:OnOutOfMemoryError commands run even when their header cannot be written. (#72)

Tests

CI now runs about 4,000 of OpenJDK's own regression tests (up from 2,524 in 0.1.1), split into eight shards balanced by run time, from the built bundle, and retries rate-limited framework downloads. The test runner evaluates @requires as jtreg does, expands jtreg's variables in @run lines, puts @library directories on test.src.path, and supports @clean, @run driver and @run build. Tests that need other locales run with locale data. (#32, #36, #40, #42, #43, #44, #45, #46, #47, #49, #50, #51, #54, #56, #61, #65, #67, #68, #69, #71). Pull requests run the test directories their changes can affect plus a sample of the rest. (#72)

Known limits

  • Child processes need Node; the browser still cannot start them. A child cannot use a directory that exists only in the VM, such as /jdk, as its working directory.
  • In the browser, maxHeap counts arrays of 4 KB or more; a program that allocates only small objects is not capped. Only Chromium has been tested.
  • File mappings are copies in the VM's 512 MB native memory.
  • Closing System.out or System.err does not close the host stream. A SecureDirectoryStream follows its directory's path, not the directory itself.

Full Changelog: v0.1.1...v0.1.2

0