From 9ed4a48e1410578a4ff1d956b11738d01ca872ee Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sat, 4 Nov 2023 06:52:19 +0000 Subject: [PATCH 01/31] 8318422: Allow poller threads be virtual threads Reviewed-by: michaelm --- .../sun/nio/ch/DefaultPollerProvider.java | 4 +- .../aix/classes/sun/nio/ch/PollsetPoller.java | 6 +- .../sun/nio/ch/DefaultPollerProvider.java | 30 +- .../linux/classes/sun/nio/ch/EPollPoller.java | 10 +- .../sun/nio/ch/DefaultPollerProvider.java | 10 +- .../classes/sun/nio/ch/KQueuePoller.java | 11 +- .../share/classes/sun/nio/ch/Poller.java | 538 ++++++++---------- .../classes/sun/nio/ch/PollerProvider.java | 69 ++- .../sun/nio/ch/DefaultPollerProvider.java | 20 +- .../classes/sun/nio/ch/WEPollPoller.java | 1 - test/hotspot/jtreg/ProblemList-Virtual.txt | 6 +- .../java/net/vthread/BlockingSocketOps.java | 10 +- .../channels/vthread/BlockingChannelOps.java | 10 +- 13 files changed, 347 insertions(+), 378 deletions(-) diff --git a/src/java.base/aix/classes/sun/nio/ch/DefaultPollerProvider.java b/src/java.base/aix/classes/sun/nio/ch/DefaultPollerProvider.java index df449cd6fd2..b645b735533 100644 --- a/src/java.base/aix/classes/sun/nio/ch/DefaultPollerProvider.java +++ b/src/java.base/aix/classes/sun/nio/ch/DefaultPollerProvider.java @@ -33,12 +33,12 @@ class DefaultPollerProvider extends PollerProvider { DefaultPollerProvider() { } @Override - Poller readPoller() throws IOException { + Poller readPoller(boolean subPoller) throws IOException { return new PollsetPoller(true); } @Override - Poller writePoller() throws IOException { + Poller writePoller(boolean subPoller) throws IOException { return new PollsetPoller(false); } } diff --git a/src/java.base/aix/classes/sun/nio/ch/PollsetPoller.java b/src/java.base/aix/classes/sun/nio/ch/PollsetPoller.java index 1aecbf7d57a..413568861e5 100644 --- a/src/java.base/aix/classes/sun/nio/ch/PollsetPoller.java +++ b/src/java.base/aix/classes/sun/nio/ch/PollsetPoller.java @@ -42,11 +42,12 @@ class PollsetPoller extends Poller { MAX_EVENTS_TO_POLL = 512; } + private final int event; private final int setid; private final long pollBuffer; PollsetPoller(boolean read) throws IOException { - super(read); + this.event = (read) ? Net.POLLIN : Net.POLLOUT; this.setid = Pollset.pollsetCreate(); this.pollBuffer = Pollset.allocatePollArray(MAX_EVENTS_TO_POLL); } @@ -58,8 +59,7 @@ int fdVal() { @Override void implRegister(int fd) throws IOException { - int ret = Pollset.pollsetCtl(setid, Pollset.PS_MOD, fd, - Pollset.PS_POLLPRI | (this.reading() ? Net.POLLIN : Net.POLLOUT)); + int ret = Pollset.pollsetCtl(setid, Pollset.PS_MOD, fd, Pollset.PS_POLLPRI | event); if (ret != 0) { throw new IOException("Unable to register fd " + fd); } diff --git a/src/java.base/linux/classes/sun/nio/ch/DefaultPollerProvider.java b/src/java.base/linux/classes/sun/nio/ch/DefaultPollerProvider.java index 3c1050808f3..a9b169a4657 100644 --- a/src/java.base/linux/classes/sun/nio/ch/DefaultPollerProvider.java +++ b/src/java.base/linux/classes/sun/nio/ch/DefaultPollerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.nio.ch; import java.io.IOException; +import jdk.internal.vm.ContinuationSupport; /** * Default PollerProvider for Linux. @@ -33,12 +34,31 @@ class DefaultPollerProvider extends PollerProvider { DefaultPollerProvider() { } @Override - Poller readPoller() throws IOException { - return new EPollPoller(true); + Poller.Mode defaultPollerMode() { + if (ContinuationSupport.isSupported()) { + return Poller.Mode.VTHREAD_POLLERS; + } else { + return Poller.Mode.SYSTEM_THREADS; + } } @Override - Poller writePoller() throws IOException { - return new EPollPoller(false); + int defaultReadPollers(Poller.Mode mode) { + int ncpus = Runtime.getRuntime().availableProcessors(); + if (mode == Poller.Mode.VTHREAD_POLLERS) { + return Math.min(Integer.highestOneBit(ncpus), 32); + } else { + return Math.max(Integer.highestOneBit(ncpus / 4), 1); + } + } + + @Override + Poller readPoller(boolean subPoller) throws IOException { + return new EPollPoller(subPoller, true); + } + + @Override + Poller writePoller(boolean subPoller) throws IOException { + return new EPollPoller(subPoller, false); } } diff --git a/src/java.base/linux/classes/sun/nio/ch/EPollPoller.java b/src/java.base/linux/classes/sun/nio/ch/EPollPoller.java index d3f7f97e3ab..4a8b2cdda08 100644 --- a/src/java.base/linux/classes/sun/nio/ch/EPollPoller.java +++ b/src/java.base/linux/classes/sun/nio/ch/EPollPoller.java @@ -32,18 +32,18 @@ */ class EPollPoller extends Poller { - private static final int MAX_EVENTS_TO_POLL = 512; private static final int ENOENT = 2; private final int epfd; private final int event; + private final int maxEvents; private final long address; - EPollPoller(boolean read) throws IOException { - super(read); + EPollPoller(boolean subPoller, boolean read) throws IOException { this.epfd = EPoll.create(); this.event = (read) ? EPOLLIN : EPOLLOUT; - this.address = EPoll.allocatePollArray(MAX_EVENTS_TO_POLL); + this.maxEvents = (subPoller) ? 64 : 512; + this.address = EPoll.allocatePollArray(maxEvents); } @Override @@ -68,7 +68,7 @@ void implDeregister(int fdVal) { @Override int poll(int timeout) throws IOException { - int n = EPoll.wait(epfd, address, MAX_EVENTS_TO_POLL, timeout); + int n = EPoll.wait(epfd, address, maxEvents, timeout); int i = 0; while (i < n) { long eventAddress = EPoll.getEvent(address, i); diff --git a/src/java.base/macosx/classes/sun/nio/ch/DefaultPollerProvider.java b/src/java.base/macosx/classes/sun/nio/ch/DefaultPollerProvider.java index 17e1d3425ba..dc32c2cd90c 100644 --- a/src/java.base/macosx/classes/sun/nio/ch/DefaultPollerProvider.java +++ b/src/java.base/macosx/classes/sun/nio/ch/DefaultPollerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,12 +33,12 @@ class DefaultPollerProvider extends PollerProvider { DefaultPollerProvider() { } @Override - Poller readPoller() throws IOException { - return new KQueuePoller(true); + Poller readPoller(boolean subPoller) throws IOException { + return new KQueuePoller(subPoller, true); } @Override - Poller writePoller() throws IOException { - return new KQueuePoller(false); + Poller writePoller(boolean subPoller) throws IOException { + return new KQueuePoller(subPoller, false); } } diff --git a/src/java.base/macosx/classes/sun/nio/ch/KQueuePoller.java b/src/java.base/macosx/classes/sun/nio/ch/KQueuePoller.java index dd3738b7d72..645b17e458e 100644 --- a/src/java.base/macosx/classes/sun/nio/ch/KQueuePoller.java +++ b/src/java.base/macosx/classes/sun/nio/ch/KQueuePoller.java @@ -31,17 +31,16 @@ * Poller implementation based on the kqueue facility. */ class KQueuePoller extends Poller { - private static final int MAX_EVENTS_TO_POLL = 512; - private final int kqfd; private final int filter; + private final int maxEvents; private final long address; - KQueuePoller(boolean read) throws IOException { - super(read); + KQueuePoller(boolean subPoller, boolean read) throws IOException { this.kqfd = KQueue.create(); this.filter = (read) ? EVFILT_READ : EVFILT_WRITE; - this.address = KQueue.allocatePollArray(MAX_EVENTS_TO_POLL); + this.maxEvents = (subPoller) ? 64 : 512; + this.address = KQueue.allocatePollArray(maxEvents); } @Override @@ -63,7 +62,7 @@ void implDeregister(int fdVal) { @Override int poll(int timeout) throws IOException { - int n = KQueue.poll(kqfd, address, MAX_EVENTS_TO_POLL, timeout); + int n = KQueue.poll(kqfd, address, maxEvents, timeout); int i = 0; while (i < n) { long keventAddress = KQueue.getEvent(address, i); diff --git a/src/java.base/share/classes/sun/nio/ch/Poller.java b/src/java.base/share/classes/sun/nio/ch/Poller.java index d39b5945b07..f62371d8344 100644 --- a/src/java.base/share/classes/sun/nio/ch/Poller.java +++ b/src/java.base/share/classes/sun/nio/ch/Poller.java @@ -24,52 +24,100 @@ */ package sun.nio.ch; -import java.io.IOError; import java.io.IOException; +import java.util.Arrays; import java.util.Map; -import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.locks.LockSupport; import java.util.function.BooleanSupplier; -import java.util.stream.Stream; import jdk.internal.misc.InnocuousThread; -import jdk.internal.access.JavaLangAccess; -import jdk.internal.access.SharedSecrets; import sun.security.action.GetPropertyAction; /** * Polls file descriptors. Virtual threads invoke the poll method to park * until a given file descriptor is ready for I/O. */ -public abstract class Poller { - private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); - private static final Poller[] READ_POLLERS; - private static final Poller[] WRITE_POLLERS; - private static final int READ_MASK, WRITE_MASK; - private static final boolean USE_DIRECT_REGISTER; - - // true if this is a poller for reading, false for writing - private final boolean read; +abstract class Poller { + private static final Pollers POLLERS; + static { + try { + var pollers = new Pollers(); + pollers.start(); + POLLERS = pollers; + } catch (IOException ioe) { + throw new ExceptionInInitializerError(ioe); + } + } // maps file descriptors to parked Thread private final Map map = new ConcurrentHashMap<>(); - // the queue of updates to the updater Thread - private final BlockingQueue queue = new LinkedTransferQueue<>(); + /** + * Poller mode. + */ + enum Mode { + /** + * ReadPoller and WritePoller are dedicated platform threads that block waiting + * for events and unpark virtual threads when file descriptors are ready for I/O. + */ + SYSTEM_THREADS, + + /** + * ReadPoller and WritePoller threads are virtual threads that poll for events, + * yielding between polls and unparking virtual threads when file descriptors are + * ready for I/O. If there are no events then the poller threads park until there + * are I/O events to poll. This mode helps to integrate polling with virtual + * thread scheduling. The approach is similar to the default scheme in "User-level + * Threading: Have Your Cake and Eat It Too" by Karsten and Barghi 2020 + * (https://dl.acm.org/doi/10.1145/3379483). + */ + VTHREAD_POLLERS + } /** - * Initialize a Poller for reading or writing. + * Initialize a Poller. */ - protected Poller(boolean read) { - this.read = read; + protected Poller() { } /** - * Returns true if this poller is for read (POLLIN) events. + * Returns the poller's file descriptor, used when the read and write poller threads + * are virtual threads. + * + * @throws UnsupportedOperationException if not supported + */ + int fdVal() { + throw new UnsupportedOperationException(); + } + + /** + * Register the file descriptor. + */ + abstract void implRegister(int fdVal) throws IOException; + + /** + * Deregister the file descriptor. + */ + abstract void implDeregister(int fdVal); + + /** + * Poll for events. The {@link #polled(int)} method is invoked for each + * polled file descriptor. + * + * @param timeout if positive then block for up to {@code timeout} milliseconds, + * if zero then don't block, if -1 then block indefinitely + * @return the number of file descriptors polled + */ + abstract int poll(int timeout) throws IOException; + + /** + * Callback by the poll method when a file descriptor is polled. */ - final boolean reading() { - return read; + final void polled(int fdVal) { + wakeup(fdVal); } /** @@ -79,57 +127,46 @@ final boolean reading() { * @param nanos the waiting time or 0 to wait indefinitely * @param supplier supplies a boolean to indicate if the enclosing object is open */ - public static void poll(int fdVal, int event, long nanos, BooleanSupplier supplier) + static void poll(int fdVal, int event, long nanos, BooleanSupplier supplier) throws IOException { assert nanos >= 0L; if (event == Net.POLLIN) { - readPoller(fdVal).poll(fdVal, nanos, supplier); + POLLERS.readPoller(fdVal).poll(fdVal, nanos, supplier); } else if (event == Net.POLLOUT) { - writePoller(fdVal).poll(fdVal, nanos, supplier); + POLLERS.writePoller(fdVal).poll(fdVal, nanos, supplier); } else { assert false; } } /** - * Parks the current thread until a file descriptor is ready. + * If there is a thread polling the given file descriptor for the given event then + * the thread is unparked. */ - private void poll(int fdVal, long nanos, BooleanSupplier supplier) throws IOException { - if (USE_DIRECT_REGISTER) { - pollDirect(fdVal, nanos, supplier); + static void stopPoll(int fdVal, int event) { + if (event == Net.POLLIN) { + POLLERS.readPoller(fdVal).wakeup(fdVal); + } else if (event == Net.POLLOUT) { + POLLERS.writePoller(fdVal).wakeup(fdVal); } else { - pollIndirect(fdVal, nanos, supplier); + throw new IllegalArgumentException(); } } /** - * Parks the current thread until a file descriptor is ready. This implementation - * registers the file descriptor, then parks until the file descriptor is polled. + * If there are any threads polling the given file descriptor then they are unparked. */ - private void pollDirect(int fdVal, long nanos, BooleanSupplier supplier) throws IOException { - register(fdVal); - try { - boolean isOpen = supplier.getAsBoolean(); - if (isOpen) { - if (nanos > 0) { - LockSupport.parkNanos(nanos); - } else { - LockSupport.park(); - } - } - } finally { - deregister(fdVal); - } + static void stopPoll(int fdVal) { + stopPoll(fdVal, Net.POLLIN); + stopPoll(fdVal, Net.POLLOUT); } /** - * Parks the current thread until a file descriptor is ready. This implementation - * queues the file descriptor to the update thread, then parks until the file - * descriptor is polled. + * Parks the current thread until a file descriptor is ready. */ - private void pollIndirect(int fdVal, long nanos, BooleanSupplier supplier) { - Request request = registerAsync(fdVal); + private void poll(int fdVal, long nanos, BooleanSupplier supplier) throws IOException { + register(fdVal); try { boolean isOpen = supplier.getAsBoolean(); if (isOpen) { @@ -140,7 +177,6 @@ private void pollIndirect(int fdVal, long nanos, BooleanSupplier supplier) { } } } finally { - request.awaitFinish(); deregister(fdVal); } } @@ -154,18 +190,6 @@ private void register(int fdVal) throws IOException { implRegister(fdVal); } - /** - * Queues the file descriptor to be registered by the updater thread, returning - * a Request object to track the request. - */ - private Request registerAsync(int fdVal) { - Thread previous = map.putIfAbsent(fdVal, Thread.currentThread()); - assert previous == null; - Request request = new Request(fdVal); - queue.add(request); - return request; - } - /** * Deregister the file descriptor, a no-op if already polled. */ @@ -178,96 +202,23 @@ private void deregister(int fdVal) { } /** - * A registration request queued to the updater thread. - */ - private static class Request { - private final int fdVal; - private volatile boolean done; - private volatile Thread waiter; - - Request(int fdVal) { - this.fdVal = fdVal; - } - - private int fdVal() { - return fdVal; - } - - /** - * Invoked by the updater when the request has been processed. - */ - void finish() { - done = true; - Thread waiter = this.waiter; - if (waiter != null) { - LockSupport.unpark(waiter); - } - } - - /** - * Waits for a request to be processed. - */ - void awaitFinish() { - if (!done) { - waiter = Thread.currentThread(); - boolean interrupted = false; - while (!done) { - LockSupport.park(); - if (Thread.interrupted()) { - interrupted = true; - } - } - if (interrupted) { - Thread.currentThread().interrupt(); - } - } - } - } - - /** - * Register the file descriptor. - */ - abstract void implRegister(int fdVal) throws IOException; - - /** - * Deregister the file descriptor. - */ - abstract void implDeregister(int fdVal); - - /** - * Starts the poller threads. - */ - private Poller start() { - String prefix = (read) ? "Read" : "Write"; - startThread(prefix + "-Poller", this::pollLoop); - if (!USE_DIRECT_REGISTER) { - startThread(prefix + "-Updater", this::updateLoop); - } - return this; - } - - /** - * Starts a platform thread to run the given task. + * Unparks any thread that is polling the given file descriptor. */ - private void startThread(String name, Runnable task) { - try { - Thread thread = JLA.executeOnCarrierThread(() -> - InnocuousThread.newSystemThread(name, task) - ); - thread.setDaemon(true); - thread.start(); - } catch (Exception e) { - throw new InternalError(e); + private void wakeup(int fdVal) { + Thread t = map.remove(fdVal); + if (t != null) { + LockSupport.unpark(t); } } /** - * Polling loop. + * Master polling loop. The {@link #polled(int)} method is invoked for each file + * descriptor that is polled. */ - private void pollLoop() { + private void pollerLoop() { try { for (;;) { - poll(); + poll(-1); } } catch (Exception e) { e.printStackTrace(); @@ -275,19 +226,25 @@ private void pollLoop() { } /** - * The update loop to handle updates to the interest set. + * Sub-poller polling loop. The {@link #polled(int)} method is invoked for each file + * descriptor that is polled. + * + * The sub-poller registers its file descriptor with the master poller to park until + * there are events to poll. When unparked, it does non-blocking polls and parks + * again when there are no more events. The sub-poller yields after each poll to help + * with fairness and to avoid re-registering with the master poller where possible. */ - private void updateLoop() { + private void subPollerLoop(Poller masterPoller) { + assert Thread.currentThread().isVirtual(); try { + int polled = 0; for (;;) { - Request req = null; - while (req == null) { - try { - req = queue.take(); - } catch (InterruptedException ignore) { } + if (polled == 0) { + masterPoller.poll(fdVal(), 0, () -> true); // park + } else { + Thread.yield(); } - implRegister(req.fdVal()); - req.finish(); + polled = poll(0); } } catch (Exception e) { e.printStackTrace(); @@ -295,175 +252,138 @@ private void updateLoop() { } /** - * Maps the file descriptor value to a read poller. - */ - private static Poller readPoller(int fdVal) { - return READ_POLLERS[fdVal & READ_MASK]; - } - - /** - * Maps the file descriptor value to a write poller. - */ - private static Poller writePoller(int fdVal) { - return WRITE_POLLERS[fdVal & WRITE_MASK]; - } - - /** - * Unparks any thread that is polling the given file descriptor for the - * given event. - */ - static void stopPoll(int fdVal, int event) { - if (event == Net.POLLIN) { - readPoller(fdVal).wakeup(fdVal); - } else if (event == Net.POLLOUT) { - writePoller(fdVal).wakeup(fdVal); - } else { - throw new IllegalArgumentException(); - } - } - - /** - * Unparks any threads that are polling the given file descriptor. + * The Pollers used for read and write events. */ - static void stopPoll(int fdVal) { - stopPoll(fdVal, Net.POLLIN); - stopPoll(fdVal, Net.POLLOUT); - } + private static class Pollers { + private final PollerProvider provider; + private final Poller.Mode pollerMode; + private final Poller masterPoller; + private final Poller[] readPollers; + private final Poller[] writePollers; - /** - * Unparks any thread that is polling the given file descriptor. - */ - private void wakeup(int fdVal) { - Thread t = map.remove(fdVal); - if (t != null) { - LockSupport.unpark(t); - } - } + // used by start method to executor is kept alive + private Executor executor; - /** - * Called by the polling facility when the file descriptor is polled - */ - final void polled(int fdVal) { - wakeup(fdVal); - } - - /** - * Poll for events. The {@link #polled(int)} method is invoked for each - * polled file descriptor. - * - * @param timeout if positive then block for up to {@code timeout} milliseconds, - * if zero then don't block, if -1 then block indefinitely - */ - abstract int poll(int timeout) throws IOException; + /** + * Creates the Poller instances based on configuration. + */ + Pollers() throws IOException { + PollerProvider provider = PollerProvider.provider(); + Poller.Mode mode; + String s = GetPropertyAction.privilegedGetProperty("jdk.pollerMode"); + if (s != null) { + if (s.equalsIgnoreCase(Mode.SYSTEM_THREADS.name()) || s.equals("1")) { + mode = Mode.SYSTEM_THREADS; + } else if (s.equalsIgnoreCase(Mode.VTHREAD_POLLERS.name()) || s.equals("2")) { + mode = Mode.VTHREAD_POLLERS; + } else { + throw new RuntimeException("Can't parse '" + s + "' as polling mode"); + } + } else { + mode = provider.defaultPollerMode(); + } - /** - * Poll for events, blocks indefinitely. - */ - final int poll() throws IOException { - return poll(-1); - } + // vthread poller mode needs a master poller + Poller masterPoller = (mode == Mode.VTHREAD_POLLERS) + ? provider.readPoller(false) + : null; - /** - * Poll for events, non-blocking. - */ - final int pollNow() throws IOException { - return poll(0); - } + // read pollers (or sub-pollers) + int readPollerCount = pollerCount("jdk.readPollers", provider.defaultReadPollers(mode)); + Poller[] readPollers = new Poller[readPollerCount]; + for (int i = 0; i < readPollerCount; i++) { + readPollers[i] = provider.readPoller(mode == Mode.VTHREAD_POLLERS); + } - /** - * Returns the poller's file descriptor, or -1 if none. - */ - int fdVal() { - return -1; - } + // write pollers (or sub-pollers) + int writePollerCount = pollerCount("jdk.writePollers", provider.defaultWritePollers(mode)); + Poller[] writePollers = new Poller[writePollerCount]; + for (int i = 0; i < writePollerCount; i++) { + writePollers[i] = provider.writePoller(mode == Mode.VTHREAD_POLLERS); + } - /** - * Creates the read and writer pollers. - */ - static { - PollerProvider provider = PollerProvider.provider(); - String s = GetPropertyAction.privilegedGetProperty("jdk.useDirectRegister"); - if (s == null) { - USE_DIRECT_REGISTER = provider.useDirectRegister(); - } else { - USE_DIRECT_REGISTER = "".equals(s) || Boolean.parseBoolean(s); + this.provider = provider; + this.pollerMode = mode; + this.masterPoller = masterPoller; + this.readPollers = readPollers; + this.writePollers = writePollers; } - try { - Poller[] readPollers = createReadPollers(provider); - READ_POLLERS = readPollers; - READ_MASK = readPollers.length - 1; - Poller[] writePollers = createWritePollers(provider); - WRITE_POLLERS = writePollers; - WRITE_MASK = writePollers.length - 1; - } catch (IOException ioe) { - throw new IOError(ioe); - } - } - /** - * Create the read poller(s). - */ - private static Poller[] createReadPollers(PollerProvider provider) throws IOException { - int readPollerCount = pollerCount("jdk.readPollers"); - Poller[] readPollers = new Poller[readPollerCount]; - for (int i = 0; i< readPollerCount; i++) { - var poller = provider.readPoller(); - readPollers[i] = poller.start(); + /** + * Starts the Poller threads. + */ + void start() { + if (pollerMode == Mode.VTHREAD_POLLERS) { + startPlatformThread("MasterPoller", masterPoller::pollerLoop); + ThreadFactory factory = Thread.ofVirtual() + .inheritInheritableThreadLocals(false) + .name("SubPoller-", 0) + .uncaughtExceptionHandler((t, e) -> e.printStackTrace()) + .factory(); + executor = Executors.newThreadPerTaskExecutor(factory); + Arrays.stream(readPollers).forEach(p -> { + executor.execute(() -> p.subPollerLoop(masterPoller)); + }); + Arrays.stream(writePollers).forEach(p -> { + executor.execute(() -> p.subPollerLoop(masterPoller)); + }); + } else { + Arrays.stream(readPollers).forEach(p -> { + startPlatformThread("Read-Poller", p::pollerLoop); + }); + Arrays.stream(writePollers).forEach(p -> { + startPlatformThread("Write-Poller", p::pollerLoop); + }); + } } - return readPollers; - } - /** - * Create the write poller(s). - */ - private static Poller[] createWritePollers(PollerProvider provider) throws IOException { - int writePollerCount = pollerCount("jdk.writePollers"); - Poller[] writePollers = new Poller[writePollerCount]; - for (int i = 0; i< writePollerCount; i++) { - var poller = provider.writePoller(); - writePollers[i] = poller.start(); + /** + * Returns the read poller for the given file descriptor. + */ + Poller readPoller(int fdVal) { + int index = provider.fdValToIndex(fdVal, readPollers.length); + return readPollers[index]; } - return writePollers; - } - /** - * Reads the given property name to get the poller count. If the property is - * set then the value must be a power of 2. Returns 1 if the property is not - * set. - * @throws IllegalArgumentException if the property is set to a value that - * is not a power of 2. - */ - private static int pollerCount(String propName) { - String s = GetPropertyAction.privilegedGetProperty(propName, "1"); - int count = Integer.parseInt(s); - - // check power of 2 - if (count != (1 << log2(count))) { - String msg = propName + " is set to a vale that is not a power of 2"; - throw new IllegalArgumentException(msg); + /** + * Returns the write poller for the given file descriptor. + */ + Poller writePoller(int fdVal) { + int index = provider.fdValToIndex(fdVal, writePollers.length); + return writePollers[index]; } - return count; - } - private static int log2(int n) { - return 31 - Integer.numberOfLeadingZeros(n); - } - - /** - * Return a stream of all threads blocked waiting for I/O operations. - */ - public static Stream blockedThreads() { - Stream s = Stream.empty(); - for (int i = 0; i < READ_POLLERS.length; i++) { - s = Stream.concat(s, READ_POLLERS[i].registeredThreads()); - } - for (int i = 0; i < WRITE_POLLERS.length; i++) { - s = Stream.concat(s, WRITE_POLLERS[i].registeredThreads()); + /** + * Reads the given property name to get the poller count. If the property is + * set then the value must be a power of 2. Returns 1 if the property is not + * set. + * @throws IllegalArgumentException if the property is set to a value that + * is not a power of 2. + */ + private static int pollerCount(String propName, int defaultCount) { + String s = GetPropertyAction.privilegedGetProperty(propName); + int count = (s != null) ? Integer.parseInt(s) : defaultCount; + + // check power of 2 + if (count != Integer.highestOneBit(count)) { + String msg = propName + " is set to a vale that is not a power of 2"; + throw new IllegalArgumentException(msg); + } + return count; } - return s; - } - private Stream registeredThreads() { - return map.values().stream(); + /** + * Starts a platform thread to run the given task. + */ + private void startPlatformThread(String name, Runnable task) { + try { + Thread thread = InnocuousThread.newSystemThread(name, task); + thread.setDaemon(true); + thread.setUncaughtExceptionHandler((t, e) -> e.printStackTrace()); + thread.start(); + } catch (Exception e) { + throw new InternalError(e); + } + } } } diff --git a/src/java.base/share/classes/sun/nio/ch/PollerProvider.java b/src/java.base/share/classes/sun/nio/ch/PollerProvider.java index 90bdcbd08ae..b10ec309265 100644 --- a/src/java.base/share/classes/sun/nio/ch/PollerProvider.java +++ b/src/java.base/share/classes/sun/nio/ch/PollerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,46 +25,63 @@ package sun.nio.ch; import java.io.IOException; -import java.util.ServiceConfigurationError; -import sun.security.action.GetPropertyAction; +/** + * Provider class for Poller implementations. + */ abstract class PollerProvider { + private static final PollerProvider INSTANCE = new DefaultPollerProvider(); + PollerProvider() { } /** - * Returns true if threads should register file descriptors directly, - * false to queue registrations to an updater thread. - * - * The default implementation returns false. + * Returns the system-wide PollerProvider. */ - boolean useDirectRegister() { - return false; + static PollerProvider provider() { + return INSTANCE; } /** - * Creates a Poller for read ops. + * Returns the default poller mode. + * @implSpec The default implementation uses system threads. */ - abstract Poller readPoller() throws IOException; + Poller.Mode defaultPollerMode() { + return Poller.Mode.SYSTEM_THREADS; + } /** - * Creates a Poller for write ops. + * Default number of read pollers for the given mode. The count must be a power of 2. + * @implSpec The default implementation returns 1. */ - abstract Poller writePoller() throws IOException; + int defaultReadPollers(Poller.Mode mode) { + return 1; + } /** - * Creates the PollerProvider. + * Default number of write pollers for the given mode. The count must be a power of 2. + * @implSpec The default implementation returns 1. */ - static PollerProvider provider() { - String cn = GetPropertyAction.privilegedGetProperty("jdk.PollerProvider"); - if (cn != null) { - try { - Class clazz = Class.forName(cn, true, ClassLoader.getSystemClassLoader()); - return (PollerProvider) clazz.getConstructor().newInstance(); - } catch (Exception e) { - throw new ServiceConfigurationError(null, e); - } - } else { - return new DefaultPollerProvider(); - } + int defaultWritePollers(Poller.Mode mode) { + return 1; + } + + /** + * Maps a file descriptor to an index from 0 to {@code toIndex}. + * @implSpec The default implementation is good for Unix file descriptors. + */ + int fdValToIndex(int fdVal, int toIndex) { + return fdVal & (toIndex - 1); } + + /** + * Creates a Poller for read ops. + * @param subPoller true to create a sub-poller + */ + abstract Poller readPoller(boolean subPoller) throws IOException; + + /** + * Creates a Poller for write ops. + * @param subPoller true to create a sub-poller + */ + abstract Poller writePoller(boolean subPoller) throws IOException; } diff --git a/src/java.base/windows/classes/sun/nio/ch/DefaultPollerProvider.java b/src/java.base/windows/classes/sun/nio/ch/DefaultPollerProvider.java index 67625352baf..abd2f34a229 100644 --- a/src/java.base/windows/classes/sun/nio/ch/DefaultPollerProvider.java +++ b/src/java.base/windows/classes/sun/nio/ch/DefaultPollerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,12 +33,26 @@ class DefaultPollerProvider extends PollerProvider { DefaultPollerProvider() { } @Override - Poller readPoller() throws IOException { + int defaultReadPollers(Poller.Mode mode) { + assert mode == Poller.Mode.SYSTEM_THREADS; + int ncpus = Runtime.getRuntime().availableProcessors(); + return Math.max(Integer.highestOneBit(ncpus / 8), 1); + } + + @Override + int fdValToIndex(int fdVal, int toIndex) { + return (fdVal >> 2) & (toIndex - 1); + } + + @Override + Poller readPoller(boolean subPoller) throws IOException { + assert !subPoller; return new WEPollPoller(true); } @Override - Poller writePoller() throws IOException { + Poller writePoller(boolean subPoller) throws IOException { + assert !subPoller; return new WEPollPoller(false); } } diff --git a/src/java.base/windows/classes/sun/nio/ch/WEPollPoller.java b/src/java.base/windows/classes/sun/nio/ch/WEPollPoller.java index e24bc0f83b3..21aee78d03b 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WEPollPoller.java +++ b/src/java.base/windows/classes/sun/nio/ch/WEPollPoller.java @@ -39,7 +39,6 @@ class WEPollPoller extends Poller { private final long address; WEPollPoller(boolean read) throws IOException { - super(read); this.handle = WEPoll.create(); this.event = (read) ? EPOLLIN : EPOLLOUT; this.address = WEPoll.allocatePollArray(MAX_EVENTS_TO_POLL); diff --git a/test/hotspot/jtreg/ProblemList-Virtual.txt b/test/hotspot/jtreg/ProblemList-Virtual.txt index 8f044dfaeca..7615e103d1a 100644 --- a/test/hotspot/jtreg/ProblemList-Virtual.txt +++ b/test/hotspot/jtreg/ProblemList-Virtual.txt @@ -84,11 +84,11 @@ vmTestbase/nsk/jdb/repeat/repeat001/repeat001.java 8300707 generic-all vmTestbase/nsk/jdi/ExceptionEvent/catchLocation/location002/TestDescription.java 8278470 generic-all ### -# This test always times out on windows. This is due to the test forcing OOME in the -# debuggee, which has the side affect of making the Read-Poller thread exit. Because +# This test times out on Windows and Linux. This is due to the test forcing OOME in +# the debuggee, which can lead to I/O poller threads exiting. Because # of this no vthreads can complete their reads, and the test times out as a result. -vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java 8285417 windows-all +vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java 8285417 generic-all ########## ## Tests incompatible with with virtual test thread factory. diff --git a/test/jdk/java/net/vthread/BlockingSocketOps.java b/test/jdk/java/net/vthread/BlockingSocketOps.java index d9ae36fbb77..f72cf768d22 100644 --- a/test/jdk/java/net/vthread/BlockingSocketOps.java +++ b/test/jdk/java/net/vthread/BlockingSocketOps.java @@ -24,17 +24,17 @@ /** * @test id=default * @bug 8284161 - * @summary Test virtual threads doing blocking I/O on java.net sockets + * @summary Test virtual threads doing blocking I/O on java.net Sockets * @library /test/lib * @run junit BlockingSocketOps */ /** - * @test id=direct-register - * @summary Test virtual threads doing blocking I/O on java.net sockets and with - * the I/O poller configured to use direct registration + * @test id=poller-modes + * @requires (os.family == "linux") | (os.family == "mac") * @library /test/lib - * @run junit/othervm -Djdk.useDirectRegister BlockingSocketOps + * @run junit/othervm -Djdk.pollerMode=1 BlockingSocketOps + * @run junit/othervm -Djdk.pollerMode=2 BlockingSocketOps */ /** diff --git a/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java b/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java index bf35fe22aee..7629b2e21b1 100644 --- a/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java +++ b/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java @@ -30,11 +30,11 @@ */ /** - * @test id=direct-register - * @summary Test virtual threads doing blocking I/O on NIO channels and with - * the I/O poller configured to use direct registration + * @test id=poller-modes + * @requires (os.family == "linux") | (os.family == "mac") * @library /test/lib - * @run junit/othervm -Djdk.useDirectRegister BlockingChannelOps + * @run junit/othervm -Djdk.pollerMode=1 BlockingChannelOps + * @run junit/othervm -Djdk.pollerMode=2 BlockingChannelOps */ /** @@ -507,7 +507,7 @@ void testDatagramSocketAdaptorReceive1() throws Exception { */ @Test void testDatagramSocketAdaptorReceive2() throws Exception { - testDatagramSocketAdaptorReceive(60_1000); + testDatagramSocketAdaptorReceive(60_000); } private void testDatagramSocketAdaptorReceive(int timeout) throws Exception { From 2c71ab62694fa368e9b6e4f996e6e2d1c01b56e7 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Sat, 4 Nov 2023 09:17:11 +0000 Subject: [PATCH 02/31] 8295159: DSO created with -ffast-math breaks Java floating-point arithmetic Reviewed-by: ihse, dholmes, stuefe --- make/test/JtregNativeHotspot.gmk | 1 + test/hotspot/jtreg/ProblemList.txt | 3 + .../floatingpoint/TestSubnormalDouble.java | 55 +++++++++++++++++ .../floatingpoint/TestSubnormalFloat.java | 55 +++++++++++++++++ .../compiler/floatingpoint/libfast-math.c | 60 +++++++++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalDouble.java create mode 100644 test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalFloat.java create mode 100644 test/hotspot/jtreg/compiler/floatingpoint/libfast-math.c diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk index 45efa033cff..24fcac2198e 100644 --- a/make/test/JtregNativeHotspot.gmk +++ b/make/test/JtregNativeHotspot.gmk @@ -851,6 +851,7 @@ ifeq ($(call isTargetOs, linux), true) BUILD_TEST_exeinvoke_exeinvoke.c_OPTIMIZATION := NONE BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exeFPRegs := -ldl BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libAsyncGetCallTraceTest := -ldl + BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libfast-math := -ffast-math else BUILD_HOTSPOT_JTREG_EXCLUDE += libtest-rw.c libtest-rwx.c \ exeinvoke.c exestack-gap.c exestack-tls.c libAsyncGetCallTraceTest.cpp diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 6bdbad4e796..311cd10b4f3 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -75,6 +75,9 @@ compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all compiler/codecache/CheckLargePages.java 8317831 linux-x64 +compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586 +compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586 + ############################################################################# # :hotspot_gc diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalDouble.java b/test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalDouble.java new file mode 100644 index 00000000000..7c556f1db44 --- /dev/null +++ b/test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalDouble.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8295159 + * @summary DSO created with -ffast-math breaks Java floating-point arithmetic + * @run main/othervm/native compiler.floatingpoint.TestSubnormalDouble + */ + +package compiler.floatingpoint; + +import static java.lang.System.loadLibrary; + +public class TestSubnormalDouble { + static volatile double lastDouble; + + private static void testDoubles() { + lastDouble = 0x1.0p-1074; + for (double x = lastDouble * 2; x <= 0x1.0p1022; x *= 2) { + if (x != x || x <= lastDouble) { + throw new RuntimeException("TEST FAILED: " + x); + } + lastDouble = x; + } + } + + public static void main(String[] args) { + testDoubles(); + System.out.println("Loading libfast-math.so"); + loadLibrary("fast-math"); + testDoubles(); + System.out.println("Test passed."); + } +} diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalFloat.java b/test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalFloat.java new file mode 100644 index 00000000000..f09ee1cf004 --- /dev/null +++ b/test/hotspot/jtreg/compiler/floatingpoint/TestSubnormalFloat.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8295159 + * @summary DSO created with -ffast-math breaks Java floating-point arithmetic + * @run main/othervm/native compiler.floatingpoint.TestSubnormalFloat + */ + +package compiler.floatingpoint; + +import static java.lang.System.loadLibrary; + +public class TestSubnormalFloat { + static volatile float lastFloat; + + private static void testFloats() { + lastFloat = 0x1.0p-149f; + for (float x = lastFloat * 2; x <= 0x1.0p127f; x *= 2) { + if (x != x || x <= lastFloat) { + throw new RuntimeException("TEST FAILED: " + x); + } + lastFloat = x; + } + } + + public static void main(String[] args) { + testFloats(); + System.out.println("Loading libfast-math.so"); + loadLibrary("fast-math"); + testFloats(); + System.out.println("Test passed."); + } +} diff --git a/test/hotspot/jtreg/compiler/floatingpoint/libfast-math.c b/test/hotspot/jtreg/compiler/floatingpoint/libfast-math.c new file mode 100644 index 00000000000..8a65303bc7c --- /dev/null +++ b/test/hotspot/jtreg/compiler/floatingpoint/libfast-math.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni.h" + +// See GCC bug 55522: +// +// "When used at link-time, [ GCC with -ffast-math ] may include +// libraries or startup files that change the default FPU control word +// or other similar optimizations." +// +// This breaks Java's floating point arithmetic. + +#if defined(__GNUC__) + +// On systems on which GCC bug 55522 has been fixed, this constructor +// serves to reproduce that bug for the purposes of testing HotSpot. +static void __attribute__((constructor)) set_flush_to_zero(void) { + +#if defined(__x86_64__) + +#define MXCSR_DAZ (1 << 6) /* Enable denormals are zero mode */ +#define MXCSR_FTZ (1 << 15) /* Enable flush to zero mode */ + unsigned int mxcsr = __builtin_ia32_stmxcsr (); + mxcsr |= MXCSR_DAZ | MXCSR_FTZ; + __builtin_ia32_ldmxcsr (mxcsr); + +#elif defined(__aarch64__) + +#define _FPU_FPCR_FZ (unsigned long)0x1000000 +#define _FPU_SETCW(fpcr) \ + __asm__ __volatile__ ("msr fpcr, %0" : : "r" (fpcr)); + + /* Flush to zero, round to nearest, IEEE exceptions disabled. */ + _FPU_SETCW (_FPU_FPCR_FZ); + +#endif // CPU arch + +} +#endif // defined(__GNUC__) From 2ed6a733fe4913c22dfde1a5dfc679fdb95e6891 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Mon, 6 Nov 2023 05:48:10 +0000 Subject: [PATCH 03/31] 8319165: hsdis binutils: warns on empty string as option string Reviewed-by: mli, jwilhelm, aph --- src/utils/hsdis/binutils/hsdis-binutils.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/utils/hsdis/binutils/hsdis-binutils.c b/src/utils/hsdis/binutils/hsdis-binutils.c index 86d49964f90..d011dc579b5 100644 --- a/src/utils/hsdis/binutils/hsdis-binutils.c +++ b/src/utils/hsdis/binutils/hsdis-binutils.c @@ -336,8 +336,9 @@ static void setup_app_data(struct hsdis_app_data* app_data, app_data->printf_stream, app_data->printf_callback, native_bfd, - /* On PowerPC we get warnings, if we pass empty options */ - (caller_options == NULL) ? NULL : app_data->insn_options); + /* On some archs we get warnings, if we pass empty options */ + ((caller_options == NULL) || (app_data->insn_options[0] == '\0')) + ? NULL : app_data->insn_options); /* Finish linking together the various callback blocks. */ app_data->dinfo.application_data = (void*) app_data; From 888e7969eea2b6506b5cff47cf31cce0e09cfde7 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Mon, 6 Nov 2023 10:41:09 +0000 Subject: [PATCH 04/31] 8316533: C2 compilation fails with assert(verify(phase)) failed: missing Value() optimization Reviewed-by: rcastanedalo, thartmann, roland --- .../types/TestSubTypeOfAbstractClass.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/types/TestSubTypeOfAbstractClass.java diff --git a/test/hotspot/jtreg/compiler/types/TestSubTypeOfAbstractClass.java b/test/hotspot/jtreg/compiler/types/TestSubTypeOfAbstractClass.java new file mode 100644 index 00000000000..63274b86e72 --- /dev/null +++ b/test/hotspot/jtreg/compiler/types/TestSubTypeOfAbstractClass.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8316533 + * @summary Oop of abstract class A with no subclass is subtype checked after null-check + * @run driver compiler.types.TestSubTypeOfAbstractClass + */ + +/** + * @test + * @bug 8316533 + * @summary Oop of abstract class A is subtype checked after null-check + * @requires vm.compiler2.enabled + * @run main/othervm -XX:CompileCommand=compileonly,*A::test + * -Xcomp -XX:+IgnoreUnrecognizedVMOptions -XX:+StressReflectiveCode + * compiler.types.TestSubTypeOfAbstractClass + */ + +package compiler.types; + +public class TestSubTypeOfAbstractClass { + + abstract class A { + public static A get_null() { + return null; + } + + public static boolean test() { + // NullCheck -> CastPP with type A:NotNull + // But A is abstract with no subclass, hence this type is impossible + return get_null() instanceof A; + } + } + + public static void main(String[] args) { + for (int i = 0; i < 10_000; i++ ) { + A.test(); + } + } +} From 90bb5d6b274660338a5dc80af5c4af74e3114cce Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Mon, 6 Nov 2023 12:58:15 +0000 Subject: [PATCH 05/31] 8319465: Typos in javadoc of com.sun.management.OperatingSystemMXBean methods Reviewed-by: dholmes, kevinw, dfuchs --- .../classes/com/sun/management/OperatingSystemMXBean.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java b/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java index 04497ed9807..bd9009cff15 100644 --- a/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java +++ b/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,7 +134,7 @@ public interface OperatingSystemMXBean extends * double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs * were idle during the recent period of time observed, while a value * of 1.0 means that all CPUs were actively running 100% of the time - * during the recent period being observed. All values betweens 0.0 and + * during the recent period being observed. All values between 0.0 and * 1.0 are possible depending of the activities going on in the system. * If the system recent cpu usage is not available, the method returns a * negative value. @@ -157,7 +157,7 @@ public interface OperatingSystemMXBean extends * is a double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs * were idle during the recent period of time observed, while a value * of 1.0 means that all CPUs were actively running 100% of the time - * during the recent period being observed. All values betweens 0.0 and + * during the recent period being observed. All values between 0.0 and * 1.0 are possible depending of the activities going on. * If the recent cpu usage is not available, the method returns a * negative value. @@ -176,7 +176,7 @@ public interface OperatingSystemMXBean extends * CPUs were actively running threads from the JVM 100% of the time * during the recent period being observed. Threads from the JVM include * the application threads as well as the JVM internal threads. All values - * betweens 0.0 and 1.0 are possible depending of the activities going on + * between 0.0 and 1.0 are possible depending of the activities going on * in the JVM process and the whole system. If the Java Virtual Machine * recent CPU usage is not available, the method returns a negative value. * From 9f238741e48fed3ae5c010a64ba8827d73aaec59 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Mon, 6 Nov 2023 13:29:48 +0000 Subject: [PATCH 06/31] 4365952: Cannot disable JFileChooser Reviewed-by: prr, abhiscxk --- .../com/apple/laf/AquaFileChooserUI.java | 11 ++ .../java/swing/plaf/gtk/GTKFileChooserUI.java | 5 + .../classes/javax/swing/JFileChooser.java | 20 +++ .../swing/plaf/basic/BasicFileChooserUI.java | 3 + .../swing/plaf/basic/BasicLookAndFeel.java | 2 +- .../swing/plaf/basic/BasicScrollPaneUI.java | 3 +- .../share/classes/sun/swing/FilePane.java | 4 + .../plaf/windows/WindowsFileChooserUI.java | 8 + .../JFileChooser/FileChooserDisableTest.java | 162 ++++++++++++++++++ 9 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 test/jdk/javax/swing/JFileChooser/FileChooserDisableTest.java diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java index 0a843f3fa71..e4b112cc297 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java @@ -744,6 +744,10 @@ public DoubleClickListener(final JTableExtension list) { public void mouseClicked(final MouseEvent e) { if (e.getClickCount() != 2) return; + if (!getFileChooser().isEnabled()) { + return; + } + final int index = list.locationToIndex(e.getPoint()); if (index < 0) return; @@ -1500,6 +1504,9 @@ public JSortingTableHeader(final TableColumnModel cm) { // Instead of dragging, it selects which one to sort by public void setDraggedColumn(final TableColumn aColumn) { + if (!getFileChooser().isEnabled()) { + return; + } if (aColumn != null) { final int colIndex = aColumn.getModelIndex(); if (colIndex != fSortColumn) { @@ -1840,6 +1847,10 @@ public void mouseClicked(final MouseEvent e) { // The autoscroller can generate drag events outside the Table's range. if ((column == -1) || (row == -1)) { return; } + if (!getFileChooser().isEnabled()) { + return; + } + final File clickedFile = (File)(fFileList.getValueAt(row, 0)); // rdar://problem/3734130 -- don't populate the text field if this file isn't selectable in this mode. diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index 8f1759f44e9..79c86de16c6 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -435,6 +435,11 @@ public DoubleClickListener(JList list) { } public void mouseClicked(MouseEvent e) { + + if (!getFileChooser().isEnabled()) { + return; + } + if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) { int index = list.locationToIndex(e.getPoint()); if (index >= 0) { diff --git a/src/java.desktop/share/classes/javax/swing/JFileChooser.java b/src/java.desktop/share/classes/javax/swing/JFileChooser.java index eb4263349df..a5802e26938 100644 --- a/src/java.desktop/share/classes/javax/swing/JFileChooser.java +++ b/src/java.desktop/share/classes/javax/swing/JFileChooser.java @@ -2078,4 +2078,24 @@ public void hierarchyChanged(HierarchyEvent e) { } } } + + /** + * {@inheritDoc} + * @param enabled {@inheritDoc} + */ + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + setEnabled(this, enabled); + } + + private static void setEnabled(Container container, boolean enabled) { + for (Component component : container.getComponents()) { + component.setEnabled(enabled); + if (component instanceof Container) { + setEnabled((Container) component, enabled); + } + } + } + } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java index 2662686ff99..57bd6664e1a 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -643,6 +643,9 @@ private class Handler implements MouseListener, ListSelectionListener { public void mouseClicked(MouseEvent evt) { // Note: we can't depend on evt.getSource() because of backward // compatibility + if (!getFileChooser().isEnabled()) { + return; + } if (list != null && SwingUtilities.isLeftMouseButton(evt) && (evt.getClickCount()%2 == 0)) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java index 0a861e76a8a..0f7857e992b 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -2228,7 +2228,7 @@ public void eventDispatched(AWTEvent ev) { src = (JComponent) ((BasicSplitPaneDivider)c).getParent(); } - if(src != null) { + if(src != null && src.isEnabled()) { JPopupMenu componentPopupMenu = src.getComponentPopupMenu(); if(componentPopupMenu != null) { Point pt = src.getPopupLocation(me); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java index 49a44fbb2b2..018cf516117 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -998,7 +998,8 @@ class Handler implements ChangeListener, PropertyChangeListener, MouseWheelListe // public void mouseWheelMoved(MouseWheelEvent e) { if (scrollpane.isWheelScrollingEnabled() && - e.getWheelRotation() != 0) { + scrollpane.isEnabled() && + e.getWheelRotation() != 0) { JScrollBar toScroll = scrollpane.getVerticalScrollBar(); int direction = e.getWheelRotation() < 0 ? -1 : 1; int orientation = SwingConstants.VERTICAL; diff --git a/src/java.desktop/share/classes/sun/swing/FilePane.java b/src/java.desktop/share/classes/sun/swing/FilePane.java index 7f83625f476..ffefbb60416 100644 --- a/src/java.desktop/share/classes/sun/swing/FilePane.java +++ b/src/java.desktop/share/classes/sun/swing/FilePane.java @@ -1954,6 +1954,10 @@ private class Handler implements MouseListener { public void mouseClicked(MouseEvent evt) { JComponent source = (JComponent)evt.getSource(); + if (!source.isEnabled()) { + return; + } + int index; if (source instanceof JList) { index = SwingUtilities2.loc2IndexFileList(list, evt.getPoint()); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java index ed384932ff0..41fa0c3f048 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java @@ -371,6 +371,10 @@ public Dimension getPreferredSize() { viewMenuButton.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { + if (!getFileChooser().isEnabled()) { + return; + } + if (SwingUtilities.isLeftMouseButton(e) && !viewMenuButton.isSelected()) { viewMenuButton.setSelected(true); @@ -380,6 +384,10 @@ public void mousePressed(MouseEvent e) { }); viewMenuButton.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { + if (!getFileChooser().isEnabled()) { + return; + } + // Forbid keyboard actions if the button is not in rollover state if (e.getKeyCode() == KeyEvent.VK_SPACE && viewMenuButton.getModel().isRollover()) { viewMenuButton.setSelected(true); diff --git a/test/jdk/javax/swing/JFileChooser/FileChooserDisableTest.java b/test/jdk/javax/swing/JFileChooser/FileChooserDisableTest.java new file mode 100644 index 00000000000..a6719430405 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/FileChooserDisableTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import javax.swing.AbstractButton; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.WindowConstants; +import javax.swing.UnsupportedLookAndFeelException; + +import java.util.function.Predicate; + +/* + * @test + * @bug 4365952 + * @key headful + * @summary Test to check if JFileChooser can be disabled + * @run main FileChooserDisableTest + */ + +public class FileChooserDisableTest { + static JFrame frame; + static JFileChooser jfc; + static volatile Point movePoint; + static String buttonToolTip; + static volatile AbstractButton openBtn; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + if (laf.getClassName().toLowerCase().contains("motif")) { + continue; + } + + if (laf.getClassName().toLowerCase().contains("gtk")) { + buttonToolTip = "Open selected file."; + } else { + buttonToolTip = "Open selected file"; + } + + System.out.println("Testing LAF : " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + try { + SwingUtilities.invokeAndWait(() -> { + initialize(); + }); + String defaultDirectory = jfc.getCurrentDirectory().toString(); + robot.delay(1000); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + openBtn = clickOpenButton(); + movePoint = openBtn.getLocationOnScreen(); + }); + Dimension btnSize = openBtn.getSize(); + robot.mouseMove(movePoint.x + btnSize.width / 2, movePoint.y + btnSize.height / 2); + robot.delay(100); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); + robot.waitForIdle(); + String currentDirectory = jfc.getCurrentDirectory().toString(); + if (!currentDirectory.equals(defaultDirectory)) { + throw new RuntimeException("File chooser disable failed"); + } + System.out.println("Test Pass"); + + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + robot.delay(200); + robot.waitForIdle(); + } + } + + private static AbstractButton clickOpenButton() { + AbstractButton details = findOpenButton(jfc); + if (details == null) { + throw new Error("Didn't find 'Open Selected File' button in JFileChooser"); + } + return details; + } + + private static Component findComponent(final Container container, + final Predicate predicate) { + for (Component child : container.getComponents()) { + if (predicate.test(child)) { + return child; + } + if (child instanceof Container cont && cont.getComponentCount() > 0) { + Component result = findComponent(cont, predicate); + if (result != null) { + return result; + } + } + } + return null; + } + + private static AbstractButton findOpenButton(final Container container) { + Component result = findComponent(container, + c -> c instanceof JButton button + && buttonToolTip.equals(button.getToolTipText())); + return (AbstractButton) result; + } + + static void initialize() { + frame = new JFrame("JFileChooser Disable test"); + jfc = new JFileChooser(); + jfc.setEnabled(false); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.add(jfc, BorderLayout.CENTER); + frame.pack(); + frame.setVisible(true); + } + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Unsupported LAF: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} From 089a894a202cdd093fc0b0b396673a04227d654e Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Mon, 6 Nov 2023 13:32:10 +0000 Subject: [PATCH 07/31] 8319153: Fix: Class is a raw type in ProcessTools Reviewed-by: dholmes, mli, lmesnik, jpai --- test/lib/jdk/test/lib/process/ProcessTools.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java index 89ef5256729..b4ee084d69f 100644 --- a/test/lib/jdk/test/lib/process/ProcessTools.java +++ b/test/lib/jdk/test/lib/process/ProcessTools.java @@ -921,7 +921,7 @@ public static void main(String[] args) throws Throwable { String className = args[1]; String[] classArgs = new String[args.length - 2]; System.arraycopy(args, 2, classArgs, 0, args.length - 2); - Class c = Class.forName(className); + Class c = Class.forName(className); Method mainMethod = c.getMethod("main", new Class[] { String[].class }); mainMethod.setAccessible(true); From 1cd88bf763d6d8bb694ff519edfddb1e9744bccd Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 6 Nov 2023 13:58:52 +0000 Subject: [PATCH 08/31] 8319455: Test compiler/print/CompileCommandMemLimit.java times out Reviewed-by: thartmann, chagedorn --- .../compiler/print/CompileCommandMemLimit.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java index f10834298f9..b3be2c69820 100644 --- a/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java +++ b/test/hotspot/jtreg/compiler/print/CompileCommandMemLimit.java @@ -24,7 +24,7 @@ /* * @test id=c1_crash * @requires vm.compiler1.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,crash causes compilation to crash + * @summary Checks that -XX:CompileCommand=MemLimit,...,crash causes C1 to crash * @library /test/lib * @run driver compiler.print.CompileCommandMemLimit crash false */ @@ -32,7 +32,7 @@ /* * @test id=c2_crash * @requires vm.compiler2.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,crash causes compilation to crash + * @summary Checks that -XX:CompileCommand=MemLimit,...,crash causes C2 to crash * @library /test/lib * @run driver compiler.print.CompileCommandMemLimit crash true */ @@ -40,7 +40,7 @@ /* * @test id=c1_stop * @requires vm.compiler1.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,stop causes compilation to stop + * @summary Checks that -XX:CompileCommand=MemLimit,...,stop causes C1 to stop * @library /test/lib * @run driver compiler.print.CompileCommandMemLimit stop false */ @@ -48,7 +48,7 @@ /* * @test id=c2_stop * @requires vm.compiler2.enabled - * @summary Checks that -XX:CompileCommand=MemLimit,...,stop causes compilation to stop + * @summary Checks that -XX:CompileCommand=MemLimit,...,stop causes C2 to stop * @library /test/lib * @run driver compiler.print.CompileCommandMemLimit stop true */ @@ -87,10 +87,17 @@ private static void test(String include, String exclude) throws Exception { List options = new ArrayList(); options.add("-Xcomp"); options.add("-XX:-Inline"); + options.add("-Xmx100m"); options.add("-XX:CompileCommand=compileonly," + getTestClass() + "::*"); // We pass a very small size to guarantee the crash options.add("-XX:CompileCommand=MemStat," + getTestMethod(include) + ",print"); - options.add("-XX:CompileCommand=MemLimit," + getTestMethod(include) + ",4k" + (test_crash ? "~crash" : "")); + if (test_crash) { + options.add("-XX:CompileCommand=MemLimit," + getTestMethod(include) + ",4k~crash"); + options.add("-XX:-CreateCoredumpOnCrash"); + } else { + options.add("-XX:CompileCommand=MemLimit," + getTestMethod(include) + ",4k"); + } + if (c2) { options.add("-XX:-TieredCompilation"); } else { From b8757c8b7bc6728f765e77fdff8599d9b044a1e0 Mon Sep 17 00:00:00 2001 From: Kevin Driver Date: Mon, 6 Nov 2023 15:07:03 +0000 Subject: [PATCH 09/31] 8308453: Convert JKS test keystores in test/jdk/javax/net/ssl/etc to PKCS12 Reviewed-by: weijun --- .../ssl/SSLSession/ResumeTLS13withSNI.java | 22 +++++++----------- .../ssl/SSLSession/SSLCtxAccessToSessCtx.java | 6 ++--- .../ssl/SSLSession/SessionCacheSizeTests.java | 9 ++++--- .../ssl/SSLSession/SessionTimeOutTests.java | 6 ++--- test/jdk/javax/net/ssl/etc/keystore | Bin 6494 -> 8074 bytes test/jdk/javax/net/ssl/etc/truststore | Bin 2785 -> 3318 bytes test/jdk/javax/net/ssl/etc/unknown_keystore | Bin 2538 -> 3231 bytes .../sun/net/www/http/HttpClient/B8025710.java | 6 ++--- .../security/provider/X509Factory/BadPem.java | 10 ++++---- .../security/provider/X509Factory/BigCRL.java | 7 +++--- .../sun/security/ssl/GenSSLConfigs/main.java | 7 +++--- .../ssl/InputRecord/ClientHelloRead.java | 9 ++++--- .../ssl/SSLEngineImpl/TestBadDNForPeerCA.java | 8 +++---- .../SSLEngineImpl/TestBadDNForPeerCA12.java | 8 +++---- .../SSLSocketSSLEngineCloseInbound.java | 12 +++------- .../ssl/ServerHandshaker/GetPeerHost.java | 4 +++- .../ServerHandshaker/GetPeerHostServer.java | 8 +++---- .../ServerHandshaker/HelloExtensionsTest.java | 9 +++---- .../ssl/X509KeyManager/PreferredKey.java | 5 ++-- .../X509KeyManager/SelectOneKeyOutOfMany.java | 5 ++-- .../CertRequestOverflow.java | 8 +++---- .../X509TrustManagerImpl/CheckNullEntity.java | 5 ++-- .../X509ExtendedTMEnabled.java | 8 +++---- 23 files changed, 68 insertions(+), 94 deletions(-) diff --git a/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java b/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java index 3e70af733fb..3d05607bd39 100644 --- a/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java +++ b/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -438,13 +438,11 @@ private static void checkResumedClientHelloSNI(ByteBuffer resCliHello) private static TrustManagerFactory makeTrustManagerFactory(String tsPath, char[] pass) throws GeneralSecurityException, IOException { TrustManagerFactory tmf; - KeyStore ts = KeyStore.getInstance("JKS"); - try (FileInputStream fsIn = new FileInputStream(tsPath)) { - ts.load(fsIn, pass); - tmf = TrustManagerFactory.getInstance("SunX509"); - tmf.init(ts); - } + KeyStore ts = KeyStore.getInstance(new File(tsPath), pass); + tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + return tmf; } @@ -463,13 +461,11 @@ private static TrustManagerFactory makeTrustManagerFactory(String tsPath, private static KeyManagerFactory makeKeyManagerFactory(String ksPath, char[] pass) throws GeneralSecurityException, IOException { KeyManagerFactory kmf; - KeyStore ks = KeyStore.getInstance("JKS"); - try (FileInputStream fsIn = new FileInputStream(ksPath)) { - ks.load(fsIn, pass); - kmf = KeyManagerFactory.getInstance("SunX509"); - kmf.init(ks, pass); - } + KeyStore ks = KeyStore.getInstance(new File(ksPath), pass); + kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, pass); + return kmf; } diff --git a/test/jdk/javax/net/ssl/SSLSession/SSLCtxAccessToSessCtx.java b/test/jdk/javax/net/ssl/SSLSession/SSLCtxAccessToSessCtx.java index 4e3b8e0b076..d50a30bcc3c 100644 --- a/test/jdk/javax/net/ssl/SSLSession/SSLCtxAccessToSessCtx.java +++ b/test/jdk/javax/net/ssl/SSLSession/SSLCtxAccessToSessCtx.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -179,8 +179,8 @@ public static void main(String[] args) throws Exception { sslctx = SSLContext.getInstance("TLS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keyFilename), passwd.toCharArray()); + KeyStore ks = KeyStore.getInstance(new File(keyFilename), + passwd.toCharArray()); kmf.init(ks, passwd.toCharArray()); sslctx.init(kmf.getKeyManagers(), null, null); diff --git a/test/jdk/javax/net/ssl/SSLSession/SessionCacheSizeTests.java b/test/jdk/javax/net/ssl/SSLSession/SessionCacheSizeTests.java index bb61abb35d5..bd6891a3573 100644 --- a/test/jdk/javax/net/ssl/SSLSession/SessionCacheSizeTests.java +++ b/test/jdk/javax/net/ssl/SSLSession/SessionCacheSizeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -315,10 +315,9 @@ public static void main(String[] args) throws Exception { sslctx = SSLContext.getInstance("TLS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - KeyStore ks = KeyStore.getInstance("JKS"); - try (FileInputStream fis = new FileInputStream(keyFilename)) { - ks.load(fis, passwd.toCharArray()); - } + KeyStore ks = KeyStore.getInstance(new File(keyFilename), + passwd.toCharArray()); + kmf.init(ks, passwd.toCharArray()); sslctx.init(kmf.getKeyManagers(), null, null); sslssf = (SSLServerSocketFactory) sslctx.getServerSocketFactory(); diff --git a/test/jdk/javax/net/ssl/SSLSession/SessionTimeOutTests.java b/test/jdk/javax/net/ssl/SSLSession/SessionTimeOutTests.java index c44c12f6c59..18a31dd1dd1 100644 --- a/test/jdk/javax/net/ssl/SSLSession/SessionTimeOutTests.java +++ b/test/jdk/javax/net/ssl/SSLSession/SessionTimeOutTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -342,8 +342,8 @@ public static void main(String[] args) throws Exception { sslctx = SSLContext.getInstance("TLS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keyFilename), passwd.toCharArray()); + KeyStore ks = KeyStore.getInstance(new File(keyFilename), + passwd.toCharArray()); kmf.init(ks, passwd.toCharArray()); sslctx.init(kmf.getKeyManagers(), null, null); sslssf = (SSLServerSocketFactory) sslctx.getServerSocketFactory(); diff --git a/test/jdk/javax/net/ssl/etc/keystore b/test/jdk/javax/net/ssl/etc/keystore index fc5e1ce53bf9ca25a722fa0c45057e3996e20e7e..7e2a8d69a44e0d34c2b22b040addc31045b9a917 100644 GIT binary patch literal 8074 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 Lg1-Fg6W@OU>?NZZ literal 6494 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 diff --git a/test/jdk/javax/net/ssl/etc/truststore b/test/jdk/javax/net/ssl/etc/truststore index 0ab0702512e3320be3344d54cbea352257ab3c5e..5e08b3b456604250bf266409ce701932883f122e 100644 GIT binary patch literal 3318 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 literal 2538 zcmchXX*d*W8^>og7_y8Ri8w~GO=HHEeJ4fseLDzQ#!{JVy%=k@m?4U!*On!F_7Yh; zlEah-avbFTNx`E))!*Y*7G`~L91ujl`J=%4AI0RRB##{mLh9wDxN zfdmf#0LZ1$pux-Nwc?^djkse>tWr!s2v8El1q4C?kZ4fB@_X`?$=*jqe=lUTaQz(G z;;_N9qBDH^MCe&Z=~_vLSb&1M^*(m!z_pWmo~*gpUTNs%BSvrxT9!yTd;kkrH#V0L zvzK(UA=I0X&rV*jOJyxnTTjoo2%;vHVi59$FKsW!YJD7bmxJ~zLqg5iYT8^wtHUeH zYRaKQ`2rH*(*5lqQn?|Z8Eb&QRZ!hgcrJRVkTRohSD6nnz`-r%yt_6=_t>0}6&WqV? zbSWL-Ow%Y>pB=BVm70JlHJzhrD|zybE-bx>|vt!s&x`={a+$06NUU*;~ftKOY4?tqfK* z`z-N+z(4@-ul5)Z17`Sg7#Dp*%UJ9K9ySs}Hf8IV zS9?|8jTzK?T{xP)p0%eNn~C8U41%RGd-Tc-86{+YP4C!ws^U{N>>xjK8} z`VJ#nX^b!>|NqYj3|^EZENb3-9}iI8ID3NoxH(F-Hg<2^%458fAcmO=(k#mZZ}FMB&?Z%6D-YbR&VV3;XVrdXa2Lu0|z(LF<^o$Qdo#Z121p%BC5AkKZ; zs*`J4h3l+KYh`4t)pWvjO+Jyuyddd<Cj=FMY#AX=~w)oG%W&>20!FMlXq3+$e8Z zk6BN%y#c=`E43z^5{K`k7Bb!UP0nuyWa<@*P{;p3T~Iw|hkL17LAR5@r2q@;~+CYX7I)eNl(t>o7 z$Sq+$ec>K_btybJNHP?#pnxqnS zQZ8WA)1}Gxu4!>me*O|9oD==rq^;~Vy{VUfSH^tx$aXPJLyEu$>L@MI1)pN!>$U=0N7i;`AH==NReMK$ zQsJo3Y||2&S>5(c`D65+jS*Z87Jb>w&gNF@sGZ5;6&NQe>hXEh6_F()aTKD7#v+r_ zUoxwT3QM-Ukt#k@SS2V`UqU4N7e>Or3Cp`}?7M{lPpJ$PZM2t~r6-ogOwZacZQ%dE8UH!J|o@3{}xuTGysPI z@th-O3Pu{Ub?PnvK-1&*(}ep^Yl3)Su7~=>#s*vUyEVm&a`1=`1a5BA7sy+YdskOz QIzH-P5#g!Gu&A{^0NpqMI{*Lx diff --git a/test/jdk/sun/net/www/http/HttpClient/B8025710.java b/test/jdk/sun/net/www/http/HttpClient/B8025710.java index 0c3a9344459..490f6aacb23 100644 --- a/test/jdk/sun/net/www/http/HttpClient/B8025710.java +++ b/test/jdk/sun/net/www/http/HttpClient/B8025710.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -264,8 +264,8 @@ class HttpServer extends Thread implements Closeable { HttpServer() throws Exception { super("HttpServer Thread"); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keystorefile), passphrase.toCharArray()); + KeyStore ks = KeyStore.getInstance(new File(keystorefile), + passphrase.toCharArray()); KeyManagerFactory factory = KeyManagerFactory.getInstance("SunX509"); factory.init(ks, passphrase.toCharArray()); SSLContext ctx = SSLContext.getInstance("TLS"); diff --git a/test/jdk/sun/security/provider/X509Factory/BadPem.java b/test/jdk/sun/security/provider/X509Factory/BadPem.java index 69682ff7d19..c63f9295123 100644 --- a/test/jdk/sun/security/provider/X509Factory/BadPem.java +++ b/test/jdk/sun/security/provider/X509Factory/BadPem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,8 +28,9 @@ * @modules java.base/sun.security.provider */ +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; +import java.io.File; import java.io.PrintStream; import java.security.KeyStore; import java.security.cert.CertificateException; @@ -38,7 +39,6 @@ import sun.security.provider.X509Factory; import java.security.cert.CertificateFactory; -import java.io.ByteArrayInputStream; public class BadPem { @@ -49,8 +49,8 @@ public static void main(String[] args) throws Exception { String alias = "dummy"; CertificateFactory cf = CertificateFactory.getInstance("X.509"); - KeyStore keyStore = KeyStore.getInstance("JKS"); - keyStore.load(new FileInputStream(ks), pass.toCharArray()); + KeyStore keyStore = KeyStore.getInstance(new File(ks), + pass.toCharArray()); byte[] cert = keyStore.getCertificate(alias).getEncoded(); // 8074935 diff --git a/test/jdk/sun/security/provider/X509Factory/BigCRL.java b/test/jdk/sun/security/provider/X509Factory/BigCRL.java index eab4e7499f8..4709a34623d 100644 --- a/test/jdk/sun/security/provider/X509Factory/BigCRL.java +++ b/test/jdk/sun/security/provider/X509Factory/BigCRL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ * @run main/othervm -Xshare:off -Xmx1024m BigCRL */ +import java.io.File; import java.io.FileInputStream; import java.math.BigInteger; import java.security.KeyStore; @@ -49,8 +50,8 @@ public static void main(String[] args) throws Exception { String pass = "passphrase"; String alias = "dummy"; - KeyStore keyStore = KeyStore.getInstance("JKS"); - keyStore.load(new FileInputStream(ks), pass.toCharArray()); + KeyStore keyStore = KeyStore.getInstance(new File(ks), + pass.toCharArray()); Certificate signerCert = keyStore.getCertificate(alias); byte[] encoded = signerCert.getEncoded(); X509CertImpl signerCertImpl = new X509CertImpl(encoded); diff --git a/test/jdk/sun/security/ssl/GenSSLConfigs/main.java b/test/jdk/sun/security/ssl/GenSSLConfigs/main.java index 6fcb39cea7c..50487634f46 100644 --- a/test/jdk/sun/security/ssl/GenSSLConfigs/main.java +++ b/test/jdk/sun/security/ssl/GenSSLConfigs/main.java @@ -7,7 +7,7 @@ */ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -190,9 +190,8 @@ private static void initContext() System.setProperty("javax.net.ssl.trustStore", testRoot + "/../../../../javax/net/ssl/etc/truststore"); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(testRoot - + "/../../../../javax/net/ssl/etc/truststore"), + KeyStore ks = KeyStore.getInstance(new File(testRoot + + "/../../../../javax/net/ssl/etc/truststore"), "passphrase".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, "passphrase".toCharArray()); diff --git a/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java b/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java index 4b0c19015e2..dab438ea9b9 100644 --- a/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java +++ b/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ */ import java.io.BufferedReader; -import java.io.FileInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; @@ -146,10 +146,9 @@ public static void main(String args[]) throws Exception ctx = SSLContext.getInstance("TLS"); kmf = KeyManagerFactory.getInstance("SunX509"); - ks = KeyStore.getInstance("JKS"); + ks = KeyStore.getInstance(new File(System.getProperty( + "javax.net.ssl.keyStore")), passphrase); - ks.load(new FileInputStream(System.getProperty( - "javax.net.ssl.keyStore")), passphrase); kmf.init(ks, passphrase); ctx.init(kmf.getKeyManagers(), null, null); diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java index 06e2aa94b35..20b4c39afb1 100644 --- a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java +++ b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java @@ -37,6 +37,7 @@ import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManagerFactory; +import java.io.File; import java.io.FileInputStream; import java.nio.ByteBuffer; import java.security.KeyStore; @@ -101,13 +102,10 @@ public static void main(String[] args) throws Exception { public TestBadDNForPeerCA() throws Exception { - KeyStore ks = KeyStore.getInstance("JKS"); - KeyStore ts = KeyStore.getInstance("JKS"); - char[] passphrase = passwd.toCharArray(); - ks.load(new FileInputStream(keyStoreFile), passphrase); - ts.load(new FileInputStream(keyStoreFile), passphrase); + KeyStore ks = KeyStore.getInstance(new File(keyStoreFile), passphrase); + KeyStore ts = KeyStore.getInstance(new File(keyStoreFile), passphrase); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java index 701620a7502..527ceb406c6 100644 --- a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java +++ b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java @@ -37,6 +37,7 @@ import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManagerFactory; +import java.io.File; import java.io.FileInputStream; import java.nio.ByteBuffer; import java.security.KeyStore; @@ -124,13 +125,10 @@ public static void main(String[] args) throws Exception { public TestBadDNForPeerCA12() throws Exception { - KeyStore ks = KeyStore.getInstance("JKS"); - KeyStore ts = KeyStore.getInstance("JKS"); - char[] passphrase = passwd.toCharArray(); - ks.load(new FileInputStream(keyStoreFile), passphrase); - ts.load(new FileInputStream(keyStoreFile), passphrase); + KeyStore ks = KeyStore.getInstance(new File(keyStoreFile), passphrase); + KeyStore ts = KeyStore.getInstance(new File(keyStoreFile), passphrase); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java index abf1571cadc..e084bdd3367 100644 --- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java +++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketSSLEngineCloseInbound.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,16 +173,10 @@ public static void main(String[] args) throws Exception { */ public SSLSocketSSLEngineCloseInbound(String protocol) throws Exception { - KeyStore ks = KeyStore.getInstance("JKS"); - KeyStore ts = KeyStore.getInstance("JKS"); - char[] passphrase = "passphrase".toCharArray(); - try (FileInputStream keyFile = new FileInputStream(keyFilename); - FileInputStream trustFile = new FileInputStream(trustFilename)) { - ks.load(keyFile, passphrase); - ts.load(trustFile, passphrase); - } + KeyStore ks = KeyStore.getInstance(new File(keyFilename), passphrase); + KeyStore ts = KeyStore.getInstance(new File(trustFilename), passphrase); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); diff --git a/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHost.java b/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHost.java index 96180df92be..664f9b2dd49 100644 --- a/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHost.java +++ b/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHost.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ public static void main(String[] argv) throws Exception { String testRoot = System.getProperty("test.src", "."); System.setProperty("javax.net.ssl.trustStore", testRoot + "/../../../../javax/net/ssl/etc/truststore"); + System.setProperty("javax.net.ssl.trustStoreType", "PKCS12"); + System.setProperty("javax.net.ssl.trustStorePassword", "passphrase"); GetPeerHostServer server = new GetPeerHostServer(); server.start(); GetPeerHostClient client = diff --git a/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHostServer.java b/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHostServer.java index afcaaf4b088..44a1e3b175a 100644 --- a/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHostServer.java +++ b/test/jdk/sun/security/ssl/ServerHandshaker/GetPeerHostServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,12 +49,10 @@ public GetPeerHostServer () try { SSLContext ctx = SSLContext.getInstance("TLS"); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - KeyStore ks = KeyStore.getInstance("JKS"); char[] passphrase = "passphrase".toCharArray(); String testRoot = System.getProperty("test.src", "."); - ks.load(new FileInputStream(testRoot - + "/../../../../javax/net/ssl/etc/keystore"), - passphrase); + KeyStore ks = KeyStore.getInstance(new File(testRoot + + "/../../../../javax/net/ssl/etc/keystore"), passphrase); kmf.init(ks, passphrase); ctx.init(kmf.getKeyManagers(), null, null); ServerSocketFactory ssf = ctx.getServerSocketFactory(); diff --git a/test/jdk/sun/security/ssl/ServerHandshaker/HelloExtensionsTest.java b/test/jdk/sun/security/ssl/ServerHandshaker/HelloExtensionsTest.java index 392e882a19a..b8ac579f8fe 100644 --- a/test/jdk/sun/security/ssl/ServerHandshaker/HelloExtensionsTest.java +++ b/test/jdk/sun/security/ssl/ServerHandshaker/HelloExtensionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,13 +254,10 @@ static private SSLEngine createSSLEngine(String keyFile, String trustFile) SSLEngine ssle; - KeyStore ks = KeyStore.getInstance("JKS"); - KeyStore ts = KeyStore.getInstance("JKS"); - char[] passphrase = "passphrase".toCharArray(); - ks.load(new FileInputStream(keyFile), passphrase); - ts.load(new FileInputStream(trustFile), passphrase); + KeyStore ks = KeyStore.getInstance(new File(keyFile), passphrase); + KeyStore ts = KeyStore.getInstance(new File(trustFile), passphrase); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); diff --git a/test/jdk/sun/security/ssl/X509KeyManager/PreferredKey.java b/test/jdk/sun/security/ssl/X509KeyManager/PreferredKey.java index 0f249f53516..5086463b589 100644 --- a/test/jdk/sun/security/ssl/X509KeyManager/PreferredKey.java +++ b/test/jdk/sun/security/ssl/X509KeyManager/PreferredKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,8 +71,7 @@ public static void main(String[] args) throws Exception { "/" + keyStoreFile; char [] password = passwd.toCharArray(); - ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keyFilename), password); + ks = KeyStore.getInstance(new File(keyFilename), password); kmf = KeyManagerFactory.getInstance("NewSunX509"); kmf.init(ks, password); km = (X509KeyManager) kmf.getKeyManagers()[0]; diff --git a/test/jdk/sun/security/ssl/X509KeyManager/SelectOneKeyOutOfMany.java b/test/jdk/sun/security/ssl/X509KeyManager/SelectOneKeyOutOfMany.java index b0348fec841..f05c32b3079 100644 --- a/test/jdk/sun/security/ssl/X509KeyManager/SelectOneKeyOutOfMany.java +++ b/test/jdk/sun/security/ssl/X509KeyManager/SelectOneKeyOutOfMany.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,8 +70,7 @@ public static void main(String[] args) throws Exception { * Setup the tests. */ kmf = KeyManagerFactory.getInstance("SunX509"); - ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keyFilename), passphrase); + ks = KeyStore.getInstance(new File(keyFilename), passphrase); kmf.init(ks, passphrase); km = (X509KeyManager) kmf.getKeyManagers()[0]; diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/CertRequestOverflow.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/CertRequestOverflow.java index c91840fa8ed..36bb6ccf01f 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/CertRequestOverflow.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/CertRequestOverflow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -192,13 +192,11 @@ private SSLContext getContext(boolean server) throws Exception { "/" + trustStoreFile; KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keyFilename), cpasswd); + KeyStore ks = KeyStore.getInstance(new File(keyFilename), cpasswd); kmf.init(ks, cpasswd); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); - KeyStore ts = KeyStore.getInstance("JKS"); - ts.load(new FileInputStream(trustFilename), cpasswd); + KeyStore ts = KeyStore.getInstance(new File(trustFilename), cpasswd); tmf.init(ts); TrustManager tms[] = tmf.getTrustManagers(); diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/CheckNullEntity.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/CheckNullEntity.java index 452fe1b4570..550cb8227cb 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/CheckNullEntity.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/CheckNullEntity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,8 +65,7 @@ private void initialize() throws Exception { "/" + trustStoreFile; char[] passphrase = "passphrase".toCharArray(); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(trustFilename), passphrase); + KeyStore ks = KeyStore.getInstance(new File(trustFilename), passphrase); for (Enumeration e = ks.aliases() ; e.hasMoreElements() ;) { String alias = (String)e.nextElement(); diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java index d0eb242442e..337f36979bb 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,13 +181,11 @@ private SSLContext getContext(boolean server) throws Exception { "/" + trustStoreFile; KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(new FileInputStream(keyFilename), cpasswd); + KeyStore ks = KeyStore.getInstance(new File(keyFilename), cpasswd); kmf.init(ks, cpasswd); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); - KeyStore ts = KeyStore.getInstance("JKS"); - ts.load(new FileInputStream(trustFilename), cpasswd); + KeyStore ts = KeyStore.getInstance(new File(trustFilename), cpasswd); tmf.init(ts); TrustManager tms[] = tmf.getTrustManagers(); From c4da7336d80dbb695fd20ec8595cc739fd6a0346 Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Mon, 6 Nov 2023 15:09:26 +0000 Subject: [PATCH 10/31] 8319316: Clarify text around which layouts a linker supports Reviewed-by: mcimadamore --- .../classes/java/lang/foreign/Linker.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index 1a39f9db3b3..c1304b8fc89 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -224,8 +224,8 @@ * * *

- * All native linker implementations operate on a subset of memory layouts. More formally, a layout {@code L} - * is supported by a native linker {@code NL} if: + * All native linker implementations support a well-defined subset of layouts. More formally, + * a layout {@code L} is supported by a native linker {@code NL} if: *

    *
  • {@code L} is a value layout {@code V} and {@code V.withoutName()} is a canonical layout
  • *
  • {@code L} is a sequence layout {@code S} and all the following conditions hold: @@ -244,6 +244,22 @@ *
  • *
* + * Linker implementations may optionally support additional layouts, such as packed struct layouts. + * A packed struct is a struct in which there is at least one member layout {@code L} that has an alignment + * constraint less strict than its natural alignment. This allows avoiding padding between member layouts, + * as well as avoiding padding at the end of the struct layout. For example: + * {@snippet lang = java: + * // No padding between the 2 element layouts: + * MemoryLayout noFieldPadding = MemoryLayout.structLayout( + * ValueLayout.JAVA_INT, + * ValueLayout.JAVA_DOUBLE.withByteAlignment(4)); + * + * // No padding at the end of the struct: + * MemoryLayout noTrailingPadding = MemoryLayout.structLayout( + * ValueLayout.JAVA_DOUBLE.withByteAlignment(4), + * ValueLayout.JAVA_INT); + * } + *

* A native linker only supports function descriptors whose argument/return layouts are layouts supported by that linker * and are not sequence layouts. * From 9f5a1937c0e2a63f6840b6f37a48f4b4983c7442 Mon Sep 17 00:00:00 2001 From: "lawrence.andrews" Date: Mon, 6 Nov 2023 20:10:51 +0000 Subject: [PATCH 11/31] 8318580: "javax/swing/MultiMonitor/MultimonVImage.java failing with Error. Can't find library: /open/test/jdk/java/awt/regtesthelpers" after JDK-8316053 Reviewed-by: serb, aivanov --- test/jdk/javax/swing/MultiMonitor/MultimonVImage.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/jdk/javax/swing/MultiMonitor/MultimonVImage.java b/test/jdk/javax/swing/MultiMonitor/MultimonVImage.java index 730424e306c..42cb9c96da5 100644 --- a/test/jdk/javax/swing/MultiMonitor/MultimonVImage.java +++ b/test/jdk/javax/swing/MultiMonitor/MultimonVImage.java @@ -28,7 +28,8 @@ * @summary displays an animating fps (frames per second) * counter. When the window is dragged from monitor to monitor, * the speed of the animation should not change too greatly. - * @library /open/test/jdk/java/awt/regtesthelpers + * @library /java/awt/regtesthelpers + * @build PassFailJFrame * @run main/manual MultimonVImage */ @@ -180,4 +181,5 @@ public void run() { component.repaint(); } } -} \ No newline at end of file +} + From c0e584494b5a438b0db1a450dacde434363915b4 Mon Sep 17 00:00:00 2001 From: "Marc R. Hoffmann" Date: Tue, 7 Nov 2023 06:37:45 +0000 Subject: [PATCH 12/31] 8319450: New methods java.net.InetXAddress.ofLiteral() miss @since tag Reviewed-by: dfuchs, aefimov, vtewari, jpai --- src/java.base/share/classes/java/net/Inet4Address.java | 1 + src/java.base/share/classes/java/net/Inet6Address.java | 1 + src/java.base/share/classes/java/net/InetAddress.java | 1 + 3 files changed, 3 insertions(+) diff --git a/src/java.base/share/classes/java/net/Inet4Address.java b/src/java.base/share/classes/java/net/Inet4Address.java index 9f1def3d5f8..bef9fa9500d 100644 --- a/src/java.base/share/classes/java/net/Inet4Address.java +++ b/src/java.base/share/classes/java/net/Inet4Address.java @@ -173,6 +173,7 @@ class Inet4Address extends InetAddress { * @throws IllegalArgumentException if the {@code ipv4AddressLiteral} cannot be * parsed as an IPv4 address literal. * @throws NullPointerException if the {@code ipv4AddressLiteral} is {@code null}. + * @since 22 */ public static Inet4Address ofLiteral(String ipv4AddressLiteral) { Objects.requireNonNull(ipv4AddressLiteral); diff --git a/src/java.base/share/classes/java/net/Inet6Address.java b/src/java.base/share/classes/java/net/Inet6Address.java index 8e132cdf148..ca73a6e1cc1 100644 --- a/src/java.base/share/classes/java/net/Inet6Address.java +++ b/src/java.base/share/classes/java/net/Inet6Address.java @@ -518,6 +518,7 @@ public static Inet6Address getByAddress(String host, byte[] addr, * @throws IllegalArgumentException if the {@code ipv6AddressLiteral} cannot be * parsed as an IPv6 address literal. * @throws NullPointerException if the {@code ipv6AddressLiteral} is {@code null}. + * @since 22 */ public static InetAddress ofLiteral(String ipv6AddressLiteral) { Objects.requireNonNull(ipv6AddressLiteral); diff --git a/src/java.base/share/classes/java/net/InetAddress.java b/src/java.base/share/classes/java/net/InetAddress.java index 90d75144a08..7cf3f954235 100644 --- a/src/java.base/share/classes/java/net/InetAddress.java +++ b/src/java.base/share/classes/java/net/InetAddress.java @@ -1722,6 +1722,7 @@ static InetAddress[] getAllByName0 (String host, boolean check) * @throws NullPointerException if the {@code ipAddressLiteral} is {@code null}. * @see Inet4Address#ofLiteral(String) * @see Inet6Address#ofLiteral(String) + * @since 22 */ public static InetAddress ofLiteral(String ipAddressLiteral) { Objects.requireNonNull(ipAddressLiteral); From 75d7e4a524cf2df53595da79b38475fe9bb22bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Tue, 7 Nov 2023 08:41:49 +0000 Subject: [PATCH 13/31] 8319197: Exclude hb-subset and hb-style from compilation Reviewed-by: erikj, aivanov, prr --- make/modules/java.desktop/lib/Awt2dLibraries.gmk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index e2b473bdff7..4d5ff751981 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -493,7 +493,10 @@ else endif # hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later. - LIBFONTMANAGER_EXCLUDE_FILES += libharfbuzz/hb-ft.cc + # hb-subset and hb-style APIs are not needed, excluded to cut on compilation time. + LIBFONTMANAGER_EXCLUDE_FILES += hb-ft.cc hb-subset-cff-common.cc \ + hb-subset-cff1.cc hb-subset-cff2.cc hb-subset-input.cc hb-subset-plan.cc \ + hb-subset.cc hb-subset-instancer-solver.cc gsubgpos-context.cc hb-style.cc # list of disabled warnings and the compilers for which it was specifically added. # array-bounds -> GCC 12 on Alpine Linux From c78f2eeb1aa452f522ace8e3aeb59d0e1abdd8f5 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 7 Nov 2023 09:46:45 +0000 Subject: [PATCH 14/31] 8318678: Vector access on heap MemorySegments only works for byte[] Reviewed-by: chegar, mcimadamore, psandoz --- .../misc/X-ScopedMemoryAccess.java.template | 16 -- .../jdk/incubator/vector/AbstractVector.java | 6 + .../jdk/incubator/vector/ByteVector.java | 8 +- .../jdk/incubator/vector/DoubleVector.java | 8 +- .../jdk/incubator/vector/FloatVector.java | 8 +- .../jdk/incubator/vector/IntVector.java | 8 +- .../jdk/incubator/vector/LongVector.java | 8 +- .../jdk/incubator/vector/ShortVector.java | 8 +- .../incubator/vector/X-Vector.java.template | 8 +- .../vector/AbstractVectorLoadStoreTest.java | 53 +++- .../incubator/vector/UnalignedHeapTest.java | 129 +++++++++ .../vector/TestLoadSegmentVarious.java | 259 ++++++++++++++++++ 12 files changed, 459 insertions(+), 60 deletions(-) create mode 100644 test/jdk/jdk/incubator/vector/UnalignedHeapTest.java create mode 100644 test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java diff --git a/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template b/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template index 773b3200a60..2c7f52352aa 100644 --- a/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template +++ b/src/java.base/share/classes/jdk/internal/misc/X-ScopedMemoryAccess.java.template @@ -329,10 +329,6 @@ public class ScopedMemoryAccess { AbstractMemorySegmentImpl msp, long offset, S s, VectorSupport.LoadOperation defaultImpl) { - // @@@ Smarter alignment checking if accessing heap segment backing non-byte[] array - if (msp.maxAlignMask() > 1) { - throw new IllegalArgumentException(); - } try { return loadFromMemorySegmentScopedInternal( @@ -374,10 +370,6 @@ public class ScopedMemoryAccess { V loadFromMemorySegmentMasked(Class vmClass, Class maskClass, Class e, int length, AbstractMemorySegmentImpl msp, long offset, M m, S s, int offsetInRange, VectorSupport.LoadVectorMaskedOperation defaultImpl) { - // @@@ Smarter alignment checking if accessing heap segment backing non-byte[] array - if (msp.maxAlignMask() > 1) { - throw new IllegalArgumentException(); - } try { return loadFromMemorySegmentMaskedScopedInternal( @@ -420,10 +412,6 @@ public class ScopedMemoryAccess { V v, AbstractMemorySegmentImpl msp, long offset, VectorSupport.StoreVectorOperation defaultImpl) { - // @@@ Smarter alignment checking if accessing heap segment backing non-byte[] array - if (msp.maxAlignMask() > 1) { - throw new IllegalArgumentException(); - } try { storeIntoMemorySegmentScopedInternal( @@ -466,10 +454,6 @@ public class ScopedMemoryAccess { int length, V v, M m, AbstractMemorySegmentImpl msp, long offset, VectorSupport.StoreVectorMaskedOperation defaultImpl) { - // @@@ Smarter alignment checking if accessing heap segment backing non-byte[] array - if (msp.maxAlignMask() > 1) { - throw new IllegalArgumentException(); - } try { storeIntoMemorySegmentMaskedScopedInternal( diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java index aac198d6b63..64d681e4aee 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/AbstractVector.java @@ -25,10 +25,16 @@ package jdk.incubator.vector; import java.lang.foreign.MemorySegment; + +import jdk.internal.foreign.AbstractMemorySegmentImpl; +import jdk.internal.foreign.Utils; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.vector.VectorSupport; +import java.lang.foreign.ValueLayout; +import java.lang.reflect.Array; import java.nio.ByteOrder; +import java.util.Objects; import java.util.function.IntUnaryOperator; import static jdk.incubator.vector.VectorOperators.*; diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java index 3c9217fc985..74b9461a5cb 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ByteVector.java @@ -2845,7 +2845,7 @@ private static ReductionOperation> reductionOperati * * @param i the lane index * @return the lane element at lane index {@code i} - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract byte lane(int i); @@ -2863,7 +2863,7 @@ private static ReductionOperation> reductionOperati * @param e the value to be placed * @return the result of replacing the lane element of this vector at lane * index {@code i} with value {@code e}. - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract ByteVector withLane(int i, byte e); @@ -3281,8 +3281,6 @@ ByteVector fromBooleanArray(VectorSpecies species, * if {@code offset+N*1 < 0} * or {@code offset+N*1 >= ms.byteSize()} * for any lane {@code N} in the vector - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 @@ -3333,8 +3331,6 @@ ByteVector fromMemorySegment(VectorSpecies species, * or {@code offset+N*1 >= ms.byteSize()} * for any lane {@code N} in the vector * where the mask is set - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 39dc04cedb7..f6e9b7b01ea 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -2659,7 +2659,7 @@ private static ReductionOperation> reductionOpe * * @param i the lane index * @return the lane element at lane index {@code i} - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract double lane(int i); @@ -2677,7 +2677,7 @@ private static ReductionOperation> reductionOpe * @param e the value to be placed * @return the result of replacing the lane element of this vector at lane * index {@code i} with value {@code e}. - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract DoubleVector withLane(int i, double e); @@ -2964,8 +2964,6 @@ DoubleVector fromArray(VectorSpecies species, * if {@code offset+N*8 < 0} * or {@code offset+N*8 >= ms.byteSize()} * for any lane {@code N} in the vector - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 @@ -3021,8 +3019,6 @@ DoubleVector fromMemorySegment(VectorSpecies species, * or {@code offset+N*8 >= ms.byteSize()} * for any lane {@code N} in the vector * where the mask is set - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index 2095da4328c..7265243b6b9 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -2679,7 +2679,7 @@ private static ReductionOperation> reductionOpera * * @param i the lane index * @return the lane element at lane index {@code i} - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract float lane(int i); @@ -2697,7 +2697,7 @@ private static ReductionOperation> reductionOpera * @param e the value to be placed * @return the result of replacing the lane element of this vector at lane * index {@code i} with value {@code e}. - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract FloatVector withLane(int i, float e); @@ -2970,8 +2970,6 @@ FloatVector fromArray(VectorSpecies species, * if {@code offset+N*4 < 0} * or {@code offset+N*4 >= ms.byteSize()} * for any lane {@code N} in the vector - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 @@ -3027,8 +3025,6 @@ FloatVector fromMemorySegment(VectorSpecies species, * or {@code offset+N*4 >= ms.byteSize()} * for any lane {@code N} in the vector * where the mask is set - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index 66f6bed91fd..f9c913f823c 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java @@ -2830,7 +2830,7 @@ private static ReductionOperation> reductionOpera * * @param i the lane index * @return the lane element at lane index {@code i} - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract int lane(int i); @@ -2848,7 +2848,7 @@ private static ReductionOperation> reductionOpera * @param e the value to be placed * @return the result of replacing the lane element of this vector at lane * index {@code i} with value {@code e}. - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract IntVector withLane(int i, int e); @@ -3126,8 +3126,6 @@ IntVector fromArray(VectorSpecies species, * if {@code offset+N*4 < 0} * or {@code offset+N*4 >= ms.byteSize()} * for any lane {@code N} in the vector - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 @@ -3183,8 +3181,6 @@ IntVector fromMemorySegment(VectorSpecies species, * or {@code offset+N*4 >= ms.byteSize()} * for any lane {@code N} in the vector * where the mask is set - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index 672f3ddc3f7..9339dc8616f 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java @@ -2696,7 +2696,7 @@ private static ReductionOperation> reductionOperati * * @param i the lane index * @return the lane element at lane index {@code i} - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract long lane(int i); @@ -2714,7 +2714,7 @@ private static ReductionOperation> reductionOperati * @param e the value to be placed * @return the result of replacing the lane element of this vector at lane * index {@code i} with value {@code e}. - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract LongVector withLane(int i, long e); @@ -3005,8 +3005,6 @@ LongVector fromArray(VectorSpecies species, * if {@code offset+N*8 < 0} * or {@code offset+N*8 >= ms.byteSize()} * for any lane {@code N} in the vector - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 @@ -3062,8 +3060,6 @@ LongVector fromMemorySegment(VectorSpecies species, * or {@code offset+N*8 >= ms.byteSize()} * for any lane {@code N} in the vector * where the mask is set - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index ed74ce21653..cfe91f6e14e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java @@ -2846,7 +2846,7 @@ private static ReductionOperation> reductionOpera * * @param i the lane index * @return the lane element at lane index {@code i} - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract short lane(int i); @@ -2864,7 +2864,7 @@ private static ReductionOperation> reductionOpera * @param e the value to be placed * @return the result of replacing the lane element of this vector at lane * index {@code i} with value {@code e}. - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract ShortVector withLane(int i, short e); @@ -3275,8 +3275,6 @@ ShortVector fromCharArray(VectorSpecies species, * if {@code offset+N*2 < 0} * or {@code offset+N*2 >= ms.byteSize()} * for any lane {@code N} in the vector - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 @@ -3332,8 +3330,6 @@ ShortVector fromMemorySegment(VectorSpecies species, * or {@code offset+N*2 >= ms.byteSize()} * for any lane {@code N} in the vector * where the mask is set - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index ae4e136406b..48fc5628f25 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -3358,7 +3358,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { * * @param i the lane index * @return the lane element at lane index {@code i} - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract $type$ lane(int i); @@ -3376,7 +3376,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { * @param e the value to be placed * @return the result of replacing the lane element of this vector at lane * index {@code i} with value {@code e}. - * @throws IllegalArgumentException if the index is is out of range + * @throws IllegalArgumentException if the index is out of range * ({@code < 0 || >= length()}) */ public abstract $abstractvectortype$ withLane(int i, $type$ e); @@ -4077,8 +4077,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { * if {@code offset+N*$sizeInBytes$ < 0} * or {@code offset+N*$sizeInBytes$ >= ms.byteSize()} * for any lane {@code N} in the vector - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 @@ -4138,8 +4136,6 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { * or {@code offset+N*$sizeInBytes$ >= ms.byteSize()} * for any lane {@code N} in the vector * where the mask is set - * @throws IllegalArgumentException if the memory segment is a heap segment that is - * not backed by a {@code byte[]} array. * @throws IllegalStateException if the memory segment's session is not alive, * or if access occurs from a thread other than the thread owning the session. * @since 19 diff --git a/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java b/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java index 20eaf638909..01d4951aaa2 100644 --- a/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java +++ b/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java @@ -23,12 +23,16 @@ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.IntBuffer; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.IntFunction; +import java.util.stream.Stream; public class AbstractVectorLoadStoreTest extends AbstractVectorTest { @@ -50,12 +54,57 @@ public class AbstractVectorLoadStoreTest extends AbstractVectorTest { ); static final List> MEMORY_SEGMENT_GENERATORS = List.of( - withToString("HMS", (int s) -> + withToString("DMS", (int s) -> Arena.ofAuto().allocate(s) ), - withToString("DMS", (int s) -> { + withToString("HMS:byte[]", (int s) -> { byte[] b = new byte[s]; return MemorySegment.ofArray(b); + }), + withToString("HMS:short[]", (int s) -> { + short[] b = new short[s / Short.BYTES]; + return MemorySegment.ofArray(b); + }), + withToString("HMS:int[]", (int s) -> { + int[] b = new int[s / Integer.BYTES]; + return MemorySegment.ofArray(b); + }), + withToString("HMS:float[]", (int s) -> { + float[] b = new float[s / Float.BYTES]; + return MemorySegment.ofArray(b); + }), + withToString("HMS:long[]", (int s) -> { + long[] b = new long[s / Long.BYTES]; + return MemorySegment.ofArray(b); + }), + withToString("HMS:double[]", (int s) -> { + double[] b = new double[s / Double.BYTES]; + return MemorySegment.ofArray(b); + }), + withToString("HMS:ByteBuffer.wrap", (int s) -> { + byte[] b = new byte[s]; + ByteBuffer buff = ByteBuffer.wrap(b); + return MemorySegment.ofBuffer(buff); + }), + // Just test one of the specialized buffers + withToString("HMS:IntBuffer.wrap", (int s) -> { + int[] b = new int[s / Integer.BYTES]; + IntBuffer buff = IntBuffer.wrap(b); + return MemorySegment.ofBuffer(buff); + }), + withToString("HMS:ByteBuffer.allocate", (int s) -> { + ByteBuffer buff = ByteBuffer.allocate(s); + return MemorySegment.ofBuffer(buff); + }), + // Just test one of the specialized buffers + withToString("HMS:IntBuffer.allocate", (int s) -> { + IntBuffer buff = IntBuffer.allocate(s / Integer.BYTES); + return MemorySegment.ofBuffer(buff); + }), + // Slice + withToString("HMS:long[].asSlice", (int s) -> { + long[] b = new long[s / Long.BYTES + 1]; + return MemorySegment.ofArray(b).asSlice(Long.BYTES); }) ); diff --git a/test/jdk/jdk/incubator/vector/UnalignedHeapTest.java b/test/jdk/jdk/incubator/vector/UnalignedHeapTest.java new file mode 100644 index 00000000000..babcea75825 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/UnalignedHeapTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @modules jdk.incubator.vector + * @run testng UnalignedHeapTest + */ + +import jdk.incubator.vector.ByteVector; +import jdk.incubator.vector.DoubleVector; +import jdk.incubator.vector.FloatVector; +import jdk.incubator.vector.IntVector; +import jdk.incubator.vector.LongVector; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.Vector; +import jdk.incubator.vector.VectorSpecies; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.stream.IntStream; + +public class UnalignedHeapTest { + + // Big enough to hold all species variants for all array types + private static final int ARRAY_LEN = 1024; + + @Test + public void testByteArray() { + for (VectorSpecies species: Arrays.asList(ByteVector.SPECIES_64, ByteVector.SPECIES_128, ByteVector.SPECIES_256, ByteVector.SPECIES_512, ByteVector.SPECIES_MAX)) { + byte[] arr = new byte[ARRAY_LEN]; + IntStream.range(0, ARRAY_LEN).forEach(i -> arr[i] = (byte) i); // May wrap around + MemorySegment segment = MemorySegment.ofArray(arr).asSlice(1); + Vector vector = species.fromMemorySegment(segment, 0, ByteOrder.nativeOrder()); + byte[] expected = segment.asSlice(0, species.vectorByteSize()).toArray(ValueLayout.JAVA_BYTE); + byte[] actual = (byte[]) vector.toArray(); + assertEquals(actual, expected, species.toString()); + } + } + + @Test + public void testShortArray() { + for (VectorSpecies species: Arrays.asList(ShortVector.SPECIES_64, ShortVector.SPECIES_128, ShortVector.SPECIES_256, ShortVector.SPECIES_512, ShortVector.SPECIES_MAX)) { + short[] arr = new short[ARRAY_LEN]; + IntStream.range(0, ARRAY_LEN).forEach(i -> arr[i] = (short) i); + MemorySegment segment = MemorySegment.ofArray(arr).asSlice(1); + Vector vector = species.fromMemorySegment(segment, 0, ByteOrder.nativeOrder()); + short[] expected = segment.asSlice(0, species.vectorByteSize()).toArray(ValueLayout.JAVA_SHORT_UNALIGNED); + short[] actual = (short[]) vector.toArray(); + assertEquals(actual, expected, species.toString()); + } + } + + @Test + public void testIntArray() { + for (VectorSpecies species: Arrays.asList(IntVector.SPECIES_64, IntVector.SPECIES_128, IntVector.SPECIES_256, IntVector.SPECIES_512, IntVector.SPECIES_MAX)) { + MemorySegment segment = MemorySegment.ofArray(IntStream.range(0, ARRAY_LEN).toArray()).asSlice(1); + Vector vector = species.fromMemorySegment(segment, 0, ByteOrder.nativeOrder()); + int[] expected = segment.asSlice(0, species.vectorByteSize()).toArray(ValueLayout.JAVA_INT_UNALIGNED); + int[] actual = vector.toIntArray(); + assertEquals(actual, expected, species.toString()); + } + } + + @Test + public void testFloatArray() { + for (VectorSpecies species: Arrays.asList(FloatVector.SPECIES_64, FloatVector.SPECIES_128, FloatVector.SPECIES_256, FloatVector.SPECIES_512, FloatVector.SPECIES_MAX)) { + float[] arr = new float[ARRAY_LEN]; + IntStream.range(0, ARRAY_LEN).forEach(i -> arr[i] = (float) i); + MemorySegment segment = MemorySegment.ofArray(arr).asSlice(1); + Vector vector = species.fromMemorySegment(segment, 0, ByteOrder.nativeOrder()); + float[] expected = segment.asSlice(0, species.vectorByteSize()).toArray(ValueLayout.JAVA_FLOAT_UNALIGNED); + float[] actual = (float[]) vector.toArray(); + assertEquals(actual, expected, species.toString()); + } + } + + @Test + public void testLongArray() { + for (VectorSpecies species: Arrays.asList(LongVector.SPECIES_64, LongVector.SPECIES_128, LongVector.SPECIES_256, LongVector.SPECIES_512, LongVector.SPECIES_MAX)) { + long[] arr = new long[ARRAY_LEN]; + IntStream.range(0, ARRAY_LEN).forEach(i -> arr[i] = i); + MemorySegment segment = MemorySegment.ofArray(arr).asSlice(1); + Vector vector = species.fromMemorySegment(segment, 0, ByteOrder.nativeOrder()); + long[] expected = segment.asSlice(0, species.vectorByteSize()).toArray(ValueLayout.JAVA_LONG_UNALIGNED); + long[] actual = (long[]) vector.toArray(); + assertEquals(actual, expected, species.toString()); + } + } + + @Test + public void testDoubleArray() { + for (VectorSpecies species: Arrays.asList(DoubleVector.SPECIES_64, DoubleVector.SPECIES_128, DoubleVector.SPECIES_256, DoubleVector.SPECIES_512, DoubleVector.SPECIES_MAX)) { + double[] arr = new double[ARRAY_LEN]; + IntStream.range(0, ARRAY_LEN).forEach(i -> arr[i] = (double) i); + MemorySegment segment = MemorySegment.ofArray(arr).asSlice(1); + Vector vector = species.fromMemorySegment(segment, 0, ByteOrder.nativeOrder()); + double[] expected = segment.asSlice(0, species.vectorByteSize()).toArray(ValueLayout.JAVA_DOUBLE_UNALIGNED); + double[] actual = (double[]) vector.toArray(); + assertEquals(actual, expected, species.toString()); + } + } + +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java new file mode 100644 index 00000000000..dba8f01adfa --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +package org.openjdk.bench.jdk.incubator.vector; + +import jdk.incubator.vector.*; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.nio.ByteOrder; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 1, jvmArgsAppend = { + "--add-modules=jdk.incubator.vector", + "--enable-native-access", "ALL-UNNAMED"}) +public class TestLoadSegmentVarious { + + private static final VectorSpecies BYTE_SPECIES = VectorSpecies.ofLargestShape(byte.class); + private static final VectorSpecies INTEGER_SPECIES = VectorSpecies.ofLargestShape(int.class); + private static final VectorSpecies DOUBLE_SPECIES = VectorSpecies.ofLargestShape(double.class); + + // Must be evenly dividable by Double.BYTES + @Param("1024") + private int size; + + private byte[] byteSrcArray; + private MemorySegment byteSegment; + private int[] intSrcArray; + private MemorySegment intSegment; + private double[] doubleSrcArray; + private MemorySegment doubleSegment; + + @Setup + public void setup() { + byteSrcArray = new byte[size]; + byteDstArray = byteSrcArray.clone(); + for (int i = 0; i < byteSrcArray.length; i++) { + byteSrcArray[i] = (byte) i; + } + byteSegment = MemorySegment.ofArray(byteSrcArray); + + intSrcArray = new int[size / Integer.BYTES]; + intDstArray = intSrcArray.clone(); + for (int i = 0; i < intSrcArray.length; i++) { + intSrcArray[i] = i; + } + intSegment = MemorySegment.ofArray(intSrcArray); + + doubleSrcArray = new double[size / Double.BYTES]; + doubleDstArray = doubleSrcArray.clone(); + for (int i = 0; i < doubleSrcArray.length; i++) { + intSrcArray[i] = i; + } + doubleSegment = MemorySegment.ofArray(doubleSrcArray); + } + + // Scalar conversion + + @Benchmark + public void scalarByteVectorFromByteSegment(Blackhole bh) { + for (int i = 0; i < size; i++) { + byte[] arr = new byte[BYTE_SPECIES.length()]; + arr[i % BYTE_SPECIES.length()] = byteSegment.get(ValueLayout.JAVA_BYTE, i); + var v = ByteVector.fromArray(BYTE_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarByteVectorFromIntSegment(Blackhole bh) { + for (int i = 0; i < size; i++) { + byte[] arr = new byte[BYTE_SPECIES.length()]; + arr[i % BYTE_SPECIES.length()] = intSegment.get(ValueLayout.JAVA_BYTE, i); + var v = ByteVector.fromArray(BYTE_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarByteVectorFromDoubleSegment(Blackhole bh) { + for (int i = 0; i < size; i++) { + byte[] arr = new byte[BYTE_SPECIES.length()]; + arr[i % BYTE_SPECIES.length()] = doubleSegment.get(ValueLayout.JAVA_BYTE, i); + var v = ByteVector.fromArray(BYTE_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarIntVectorFromByteSegment(Blackhole bh) { + for (int i = 0; i < size / Integer.BYTES; i++) { + int[] arr = new int[INTEGER_SPECIES.length()]; + arr[i % INTEGER_SPECIES.length()] = byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, i * Integer.BYTES); + var v = IntVector.fromArray(INTEGER_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarIntVectorFromIntSegment(Blackhole bh) { + for (int i = 0; i < size / Integer.BYTES; i++) { + int[] arr = new int[INTEGER_SPECIES.length()]; + arr[i % INTEGER_SPECIES.length()] = intSegment.get(ValueLayout.JAVA_INT, i * Integer.BYTES); + var v = IntVector.fromArray(INTEGER_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarIntVectorFromDoubleSegment(Blackhole bh) { + for (int i = 0; i < size / Integer.BYTES; i++) { + int[] arr = new int[INTEGER_SPECIES.length()]; + arr[i % INTEGER_SPECIES.length()] = doubleSegment.get(ValueLayout.JAVA_INT, i * Integer.BYTES); + var v = IntVector.fromArray(INTEGER_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarDoubleVectorFromByteSegment(Blackhole bh) { + for (int i = 0; i < size / Double.BYTES; i ++) { + double[] arr = new double[DOUBLE_SPECIES.length()]; + arr[i % DOUBLE_SPECIES.length()] = byteSegment.get(ValueLayout.JAVA_DOUBLE_UNALIGNED, i * Double.BYTES); + var v = DoubleVector.fromArray(DOUBLE_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarDoubleVectorFromIntSegment(Blackhole bh) { + for (int i = 0; i < size / Double.BYTES; i ++) { + double[] arr = new double[DOUBLE_SPECIES.length()]; + arr[i % DOUBLE_SPECIES.length()] = intSegment.get(ValueLayout.JAVA_DOUBLE_UNALIGNED, i * Double.BYTES); + var v = DoubleVector.fromArray(DOUBLE_SPECIES, arr, 0); + bh.consume(v); + } + } + + @Benchmark + public void scalarDoubleVectorFromDoubleSegment(Blackhole bh) { + for (int i = 0; i < size / Double.BYTES; i ++) { + double[] arr = new double[DOUBLE_SPECIES.length()]; + arr[i % DOUBLE_SPECIES.length()] = doubleSegment.get(ValueLayout.JAVA_DOUBLE, i * Double.BYTES); + var v = DoubleVector.fromArray(DOUBLE_SPECIES, arr, 0); + bh.consume(v); + } + } + + // Vector conversion + + @Benchmark + public void byteVectorFromByteBackedSegment(Blackhole bh) { + for (int i = 0; i < BYTE_SPECIES.loopBound(byteSrcArray.length); i += BYTE_SPECIES.vectorByteSize()) { + var v = ByteVector.fromMemorySegment(BYTE_SPECIES, byteSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void byteVectorFromIntBackedSegment(Blackhole bh) { + for (int i = 0; i < BYTE_SPECIES.loopBound(byteSrcArray.length); i += BYTE_SPECIES.vectorByteSize()) { + var v = ByteVector.fromMemorySegment(BYTE_SPECIES, intSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void byteVectorFromDoubleBackedSegment(Blackhole bh) { + for (int i = 0; i < BYTE_SPECIES.loopBound(byteSrcArray.length); i += BYTE_SPECIES.vectorByteSize()) { + var v = ByteVector.fromMemorySegment(BYTE_SPECIES, doubleSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void intVectorFromByteBackedSegment(Blackhole bh) { + for (int i = 0; i < INTEGER_SPECIES.loopBound(intSrcArray.length); i += INTEGER_SPECIES.vectorByteSize()) { + var v = IntVector.fromMemorySegment(INTEGER_SPECIES, byteSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void intVectorFromIntBackedSegment(Blackhole bh) { + for (int i = 0; i < INTEGER_SPECIES.loopBound(intSrcArray.length); i += INTEGER_SPECIES.vectorByteSize()) { + var v = IntVector.fromMemorySegment(INTEGER_SPECIES, intSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void intVectorFromDoubleBackedSegment(Blackhole bh) { + for (int i = 0; i < INTEGER_SPECIES.loopBound(intSrcArray.length); i += INTEGER_SPECIES.vectorByteSize()) { + var v = IntVector.fromMemorySegment(INTEGER_SPECIES, doubleSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void doubleVectorFromByteBackedSegment(Blackhole bh) { + for (int i = 0; i < DOUBLE_SPECIES.loopBound(doubleSrcArray.length); i += DOUBLE_SPECIES.vectorByteSize()) { + var v = DoubleVector.fromMemorySegment(DOUBLE_SPECIES, byteSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void doubleVectorFromIntBackedSegment(Blackhole bh) { + for (int i = 0; i < DOUBLE_SPECIES.loopBound(doubleSrcArray.length); i += DOUBLE_SPECIES.vectorByteSize()) { + var v = DoubleVector.fromMemorySegment(DOUBLE_SPECIES, intSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + + @Benchmark + public void doubleVectorFromDoubleBackedSegment(Blackhole bh) { + for (int i = 0; i < DOUBLE_SPECIES.loopBound(doubleSrcArray.length); i += DOUBLE_SPECIES.vectorByteSize()) { + var v = DoubleVector.fromMemorySegment(DOUBLE_SPECIES, doubleSegment, i, ByteOrder.nativeOrder()); + bh.consume(v); + } + } + +} From 551c9b14f164873cff0bc59c6ea5b12e60439c75 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Tue, 7 Nov 2023 10:15:35 +0000 Subject: [PATCH 15/31] 8319238: JMX ThreadPoolAccTest.java is too verbose and should fail before timeout Reviewed-by: sspitsyn --- .../management/monitor/ThreadPoolAccTest.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/management/monitor/ThreadPoolAccTest.java b/test/jdk/javax/management/monitor/ThreadPoolAccTest.java index 2d2ef31b614..8218a58b410 100644 --- a/test/jdk/javax/management/monitor/ThreadPoolAccTest.java +++ b/test/jdk/javax/management/monitor/ThreadPoolAccTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,8 @@ public class ThreadPoolAccTest { + public static final int MAX_TRIES = 30; + // MBean class public static class ObservedObject implements ObservedObjectMBean { public volatile String principal; @@ -137,8 +139,18 @@ public Void run() { Subject.doAs(subject, action); } - while(!testPrincipals(monitored, monitorNames, monitor, principals)); - + sleep(500); // wait for getX method to be called, which calls setPrincipal + boolean ok = false; + for (int i = 0; i < MAX_TRIES; i++) { + ok = testPrincipals(monitored, monitorNames, monitor, principals); + if (ok) { + break; + } + sleep(1000); + } + if (!ok) { + throw new Exception("Failed: testPrincipals fails repeatedly."); + } } finally { for (int i = 0; i < 6; i++) if (monitor[i] != null) @@ -151,6 +163,9 @@ private static boolean testPrincipals(ObservedObject[] monitored, ObjectName[] m for (int i = 0; i < 6; i++) { String principal = monitored[i].principal; String expected = principals[i / 3]; + + echo("testPrincipals: monitored: " + monitored[i] + " principal: " + principal + " expected: " + expected); + if (principal == null) { echo("Task not submitted " + new Date() + ". RETRY"); return false; @@ -172,4 +187,12 @@ private static boolean testPrincipals(ObservedObject[] monitored, ObjectName[] m private static void echo(String message) { System.out.println(message); } + + public static void sleep(int ms) { + try { + Thread.currentThread().sleep(ms); + } catch (InterruptedException ie) { + // ignore + } + } } From 107925b4b3db366853a19a9c5e46fd1d01679c93 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 7 Nov 2023 11:04:43 +0000 Subject: [PATCH 16/31] 8319613: Complier error in benchmark TestLoadSegmentVarious Reviewed-by: jpai, stefank --- .../bench/jdk/incubator/vector/TestLoadSegmentVarious.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java index dba8f01adfa..58cd93f3c51 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadSegmentVarious.java @@ -69,21 +69,18 @@ public class TestLoadSegmentVarious { @Setup public void setup() { byteSrcArray = new byte[size]; - byteDstArray = byteSrcArray.clone(); for (int i = 0; i < byteSrcArray.length; i++) { byteSrcArray[i] = (byte) i; } byteSegment = MemorySegment.ofArray(byteSrcArray); intSrcArray = new int[size / Integer.BYTES]; - intDstArray = intSrcArray.clone(); for (int i = 0; i < intSrcArray.length; i++) { intSrcArray[i] = i; } intSegment = MemorySegment.ofArray(intSrcArray); doubleSrcArray = new double[size / Double.BYTES]; - doubleDstArray = doubleSrcArray.clone(); for (int i = 0; i < doubleSrcArray.length; i++) { intSrcArray[i] = i; } From f693ff86c5ca014ae32092e8555356d8d589915a Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 7 Nov 2023 11:39:41 +0000 Subject: [PATCH 17/31] 8319563: Reformat code in the FFM API Reviewed-by: mcimadamore --- .../share/classes/java/lang/foreign/MemoryLayout.java | 3 ++- .../share/classes/java/lang/foreign/MemorySegment.java | 8 ++++++-- .../share/classes/java/lang/foreign/SymbolLookup.java | 6 ++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java index 6533849a920..0f1a6efe826 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java @@ -875,7 +875,8 @@ static PaddingLayout paddingLayout(long byteSize) { static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) { MemoryLayoutUtil.requireNonNegative(elementCount); Objects.requireNonNull(elementLayout); - Utils.checkElementAlignment(elementLayout, "Element layout size is not multiple of alignment"); + Utils.checkElementAlignment(elementLayout, + "Element layout size is not multiple of alignment"); return Utils.wrapOverflow(() -> SequenceLayoutImpl.of(elementCount, elementLayout)); } diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index 19e7c41781a..f145276e814 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -1297,7 +1297,9 @@ static MemorySegment ofAddress(long address) { @ForceInline static void copy(MemorySegment srcSegment, long srcOffset, MemorySegment dstSegment, long dstOffset, long bytes) { - copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes); + copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, + dstSegment, ValueLayout.JAVA_BYTE, dstOffset, + bytes); } /** @@ -1354,7 +1356,9 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr Objects.requireNonNull(srcElementLayout); Objects.requireNonNull(dstSegment); Objects.requireNonNull(dstElementLayout); - AbstractMemorySegmentImpl.copy(srcSegment, srcElementLayout, srcOffset, dstSegment, dstElementLayout, dstOffset, elementCount); + AbstractMemorySegmentImpl.copy(srcSegment, srcElementLayout, srcOffset, + dstSegment, dstElementLayout, dstOffset, + elementCount); } /** diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java index 96e78bb1d58..4af2076fb5f 100644 --- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java +++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java @@ -228,7 +228,8 @@ static SymbolLookup loaderLookup() { @CallerSensitive @Restricted static SymbolLookup libraryLookup(String name, Arena arena) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), SymbolLookup.class, "libraryLookup"); + Reflection.ensureNativeAccess(Reflection.getCallerClass(), + SymbolLookup.class, "libraryLookup"); if (Utils.containsNullChars(name)) { throw new IllegalArgumentException("Cannot open library: " + name); } @@ -256,7 +257,8 @@ static SymbolLookup libraryLookup(String name, Arena arena) { @CallerSensitive @Restricted static SymbolLookup libraryLookup(Path path, Arena arena) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), SymbolLookup.class, "libraryLookup"); + Reflection.ensureNativeAccess(Reflection.getCallerClass(), + SymbolLookup.class, "libraryLookup"); return libraryLookup(path, RawNativeLibraries::load, arena); } From c7cfede35fe8f12a08a4228a10204b68ff6f5e56 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 7 Nov 2023 12:05:58 +0000 Subject: [PATCH 18/31] 8318144: Match on enum constants with body compiles but fails with MatchException Reviewed-by: liach, vromero --- .../java/lang/runtime/SwitchBootstraps.java | 6 +- .../lang/runtime/SwitchBootstrapsTest.java | 32 ++++++- .../javac/patterns/SwitchEnumConstants.java | 86 +++++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 test/langtools/tools/javac/patterns/SwitchEnumConstants.java diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index 4743b009970..6810fa6222d 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -394,9 +394,13 @@ private static boolean enumEqCheck(Object value, EnumDesc label, MethodHandle Object resolved; try { + if (!(value instanceof Enum enumValue)) { + return false; + } + Class clazz = label.constantType().resolveConstantDesc(lookup); - if (value.getClass() != clazz) { + if (enumValue.getDeclaringClass() != clazz) { return false; } diff --git a/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java b/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java index cbd728e33d5..1489a6d55b7 100644 --- a/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java +++ b/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java @@ -40,6 +40,7 @@ /** * @test + * @bug 8318144 * @enablePreview * @compile SwitchBootstrapsTest.java * @run testng/othervm SwitchBootstrapsTest @@ -70,7 +71,11 @@ private void testType(Object target, int start, int result, Object... labels) th } private void testEnum(Enum target, int start, int result, Object... labels) throws Throwable { - MethodType switchType = MethodType.methodType(int.class, target.getClass(), int.class); + testEnum(target.getClass(), target, start, result, labels); + } + + private void testEnum(Class targetClass, Enum target, int start, int result, Object... labels) throws Throwable { + MethodType switchType = MethodType.methodType(int.class, targetClass, int.class); MethodHandle indy = ((CallSite) BSM_ENUM_SWITCH.invoke(MethodHandles.lookup(), "", switchType, labels)).dynamicInvoker(); assertEquals((int) indy.invoke(target, start), result); assertEquals(-1, (int) indy.invoke(null, start)); @@ -138,6 +143,31 @@ public void testEnums() throws Throwable { testEnum(E1.A, 0, 0); } + public void testEnumsWithConstants() throws Throwable { + enum E { + A {}, + B {}, + C {} + } + ClassDesc eDesc = E.class.describeConstable().get(); + Object[] typeParams = new Object[] { + EnumDesc.of(eDesc, "A"), + EnumDesc.of(eDesc, "B"), + EnumDesc.of(eDesc, "C"), + "a", + String.class + }; + testType(E.A, 0, 0, typeParams); + testType(E.B, 0, 1, typeParams); + testType(E.C, 0, 2, typeParams); + testType("a", 0, 3, typeParams); + testType("x", 0, 4, typeParams); + testType('a', 0, 5, typeParams); + testEnum(E.class, E.A, 0, 0, "A", "B", "C"); + testEnum(E.class, E.B, 0, 1, "A", "B", "C"); + testEnum(E.class, E.C, 0, 2, "A", "B", "C"); + } + public void testWrongSwitchTypes() throws Throwable { MethodType[] switchTypes = new MethodType[] { MethodType.methodType(int.class, Object.class), diff --git a/test/langtools/tools/javac/patterns/SwitchEnumConstants.java b/test/langtools/tools/javac/patterns/SwitchEnumConstants.java new file mode 100644 index 00000000000..6396ea44f5f --- /dev/null +++ b/test/langtools/tools/javac/patterns/SwitchEnumConstants.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8318144 + * @summary Verify switches work in presence of enum constants that have bodies + * @compile SwitchEnumConstants.java + * @run main SwitchEnumConstants + */ + +import java.util.function.ToIntFunction; + +public class SwitchEnumConstants { + + public static void main(String... args) throws Exception { + new SwitchEnumConstants().run(); + } + + void run() throws Exception { + doRun(this::typeSwitch); + doRun(this::enumSwitch); + } + + void doRun(ToIntFunction c) throws Exception { + assertEquals(0, c.applyAsInt(E.A)); + assertEquals(1, c.applyAsInt(E.B)); + assertEquals(2, c.applyAsInt(E.C)); + assertEquals(3, c.applyAsInt("")); + } + + int typeSwitch(Object o) { + return switch (o) { + case E.A -> 0; + case E.B -> 1; + case E.C -> 2; + case String s -> 3; + default -> throw new IllegalStateException(); + }; + } + + int enumSwitch(Object o) { + if (!(o instanceof E e)) { + return 3; + } + return switch (e) { + case A -> 0; + case B -> 1; + case C -> 2; + }; + } + + + private static void assertEquals(int expected, int actual) { + if (expected != actual) { + throw new AssertionError("expected: " + expected + + ", actual: " + actual); + } + } + + enum E { + A {}, + B {}, + C {} + } +} From e8ae73ac6fbc8fb66c579321ecd859efb8346ac9 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Tue, 7 Nov 2023 12:22:40 +0000 Subject: [PATCH 19/31] 8319462: Signature.ClassTypeSig::classDesc() incorrect for inner class types Reviewed-by: asotona --- .../jdk/internal/classfile/Signature.java | 6 +++-- test/jdk/jdk/classfile/SignaturesTest.java | 22 ++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/classfile/Signature.java b/src/java.base/share/classes/jdk/internal/classfile/Signature.java index ae32ad7d84d..c9c7ae1c705 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/Signature.java +++ b/src/java.base/share/classes/jdk/internal/classfile/Signature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,7 +118,9 @@ public sealed interface ClassTypeSig /** {@return the class name, as a symbolic descriptor} */ default ClassDesc classDesc() { - return ClassDesc.ofInternalName(className()); + var outer = outerType(); + return outer.isEmpty() ? ClassDesc.ofInternalName(className()) + : outer.get().classDesc().nested(className()); } /** {@return the type arguments of the class} */ diff --git a/test/jdk/jdk/classfile/SignaturesTest.java b/test/jdk/jdk/classfile/SignaturesTest.java index 72582185f67..932f8c7e80d 100644 --- a/test/jdk/jdk/classfile/SignaturesTest.java +++ b/test/jdk/jdk/classfile/SignaturesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,14 @@ * @summary Testing Signatures. * @run junit SignaturesTest */ +import java.io.IOException; import java.lang.constant.ClassDesc; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; @@ -166,4 +168,22 @@ void testParseAndPrintSignatures() throws Exception { }); System.out.println("SignaturesTest - tested signatures of " + csc + " classes, " + msc + " methods, " + fsc + " fields and " + rsc + " record components"); } + + static class Outer { + class Inner {} + } + + static class Observer extends ArrayList.Inner>{} + + @Test + void testClassSignatureClassDesc() throws IOException { + var observerCf = Classfile.of().parse(Path.of(System.getProperty("test.classes"), "SignaturesTest$Observer.class")); + var sig = observerCf.findAttribute(Attributes.SIGNATURE).orElseThrow().asClassSignature(); + var innerSig = (ClassTypeSig) ((ClassTypeSig) sig.superclassSignature()) // ArrayList + .typeArgs().getFirst() // Outer.Inner + .boundType().orElseThrow(); // assert it's exact bound + assertEquals("Inner", innerSig.className(), "simple name in signature"); + assertEquals(Outer.Inner.class.describeConstable().orElseThrow(), innerSig.classDesc(), + "ClassDesc derived from signature"); + } } From 09abc28cea5eff1a4c42a9a3f1f00f666b984beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Lund=C3=A9n?= Date: Tue, 7 Nov 2023 13:57:12 +0000 Subject: [PATCH 20/31] 8319615: IGV incomplete gitignore Reviewed-by: rcastanedalo --- src/utils/IdealGraphVisualizer/.gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/IdealGraphVisualizer/.gitignore b/src/utils/IdealGraphVisualizer/.gitignore index 785134c4410..694f4ff7d0d 100644 --- a/src/utils/IdealGraphVisualizer/.gitignore +++ b/src/utils/IdealGraphVisualizer/.gitignore @@ -1,2 +1,6 @@ /*/target -.igv.log \ No newline at end of file +.igv.log +/all-*.dat +/lastModified/ +/localeVariants +/package-attrs.dat From 1347a226f20f5e08ef99d84b0faf5378552ee7ed Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 7 Nov 2023 14:34:33 +0000 Subject: [PATCH 21/31] 8319607: FFM: Review the language in the FFM documentation Reviewed-by: mcimadamore --- .../java/lang/foreign/AddressLayout.java | 4 +- .../classes/java/lang/foreign/Arena.java | 2 +- .../java/lang/foreign/FunctionDescriptor.java | 6 +- .../java/lang/foreign/GroupLayout.java | 2 +- .../classes/java/lang/foreign/Linker.java | 42 ++++---- .../java/lang/foreign/MemoryLayout.java | 52 +++++----- .../java/lang/foreign/MemorySegment.java | 98 +++++++++---------- .../java/lang/foreign/SegmentAllocator.java | 26 ++--- .../java/lang/foreign/SequenceLayout.java | 2 +- .../java/lang/foreign/SymbolLookup.java | 6 +- .../java/lang/foreign/ValueLayout.java | 6 +- .../java/lang/foreign/package-info.java | 10 +- 12 files changed, 128 insertions(+), 128 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/AddressLayout.java b/src/java.base/share/classes/java/lang/foreign/AddressLayout.java index ded175571be..137152d78cc 100644 --- a/src/java.base/share/classes/java/lang/foreign/AddressLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/AddressLayout.java @@ -100,7 +100,7 @@ public sealed interface AddressLayout extends ValueLayout permits ValueLayouts.O *} * * @param layout the target layout. - * @return an address layout with same characteristics as this layout, but with the provided target layout. + * @return an address layout with the same characteristics as this layout, but with the provided target layout. * @throws IllegalCallerException If the caller is in a module that does not have native access enabled * @see #targetLayout() */ @@ -114,7 +114,7 @@ public sealed interface AddressLayout extends ValueLayout permits ValueLayouts.O * * @apiNote This can be useful to compare two address layouts that have different target layouts, but are otherwise equal. * - * @return an address layout with same characteristics as this layout, but with no target layout. + * @return an address layout with the same characteristics as this layout, but with no target layout. * @see #targetLayout() */ AddressLayout withoutTargetLayout(); diff --git a/src/java.base/share/classes/java/lang/foreign/Arena.java b/src/java.base/share/classes/java/lang/foreign/Arena.java index f25b54a6b29..cdd5019b53d 100644 --- a/src/java.base/share/classes/java/lang/foreign/Arena.java +++ b/src/java.base/share/classes/java/lang/foreign/Arena.java @@ -246,7 +246,7 @@ static Arena ofShared() { * The returned segment is associated with this {@linkplain #scope() arena scope}. * The segment's {@link MemorySegment#address() address} is the starting address of the * allocated off-heap region of memory backing the segment, and the address is - * aligned according the provided alignment constraint. + * aligned according to the provided alignment constraint. * * @implSpec * Implementations of this method must return a native segment featuring the requested size, diff --git a/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java b/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java index 23c64164951..ee42e991480 100644 --- a/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java +++ b/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java @@ -70,7 +70,7 @@ public sealed interface FunctionDescriptor permits FunctionDescriptorImpl { * Returns a function descriptor with the given argument layouts inserted at the given index, into the argument * layout array of this function descriptor. * @param index the index at which to insert the arguments - * @param addedLayouts the argument layouts to insert at given index. + * @param addedLayouts the argument layouts to insert at the given index. * @return a new function descriptor, with the provided additional argument layouts. * @throws IllegalArgumentException if one of the layouts in {@code addedLayouts} is a padding layout * @throws IllegalArgumentException if {@code index < 0 || index > argumentLayouts().size()} @@ -100,7 +100,7 @@ public sealed interface FunctionDescriptor permits FunctionDescriptorImpl { * * * @apiNote A function descriptor cannot, by construction, contain any padding layouts. As such, it is not - * necessary to specify how padding layout should be mapped to carrier types. + * necessary to specify how padding layouts should be mapped to carrier types. * * @return the method type consisting of the carrier types of the layouts in this function descriptor. */ @@ -121,7 +121,7 @@ static FunctionDescriptor of(MemoryLayout resLayout, MemoryLayout... argLayouts) } /** - * Creates a function descriptor with the given argument layouts and no return layout. This is useful to model functions + * Creates a function descriptor with the given argument layouts and no return layout. This is useful for modeling functions * that return no values. * @param argLayouts the argument layouts. * @throws IllegalArgumentException if one of the layouts in {@code argLayouts} is a padding layout diff --git a/src/java.base/share/classes/java/lang/foreign/GroupLayout.java b/src/java.base/share/classes/java/lang/foreign/GroupLayout.java index 8182b0da9bf..24bec8f0439 100644 --- a/src/java.base/share/classes/java/lang/foreign/GroupLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/GroupLayout.java @@ -44,7 +44,7 @@ public sealed interface GroupLayout extends MemoryLayout permits StructLayout, U /** * {@return the member layouts of this group layout} * - * @apiNote the order in which member layouts are returned is the same order in which member layouts have + * @apiNote the order in which member layouts are returned in the same order in which member layouts have * been passed to one of the group layout factory methods (see {@link MemoryLayout#structLayout(MemoryLayout...)}, * {@link MemoryLayout#unionLayout(MemoryLayout...)}). */ diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index c1304b8fc89..53fe45d81f3 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -43,13 +43,13 @@ /** * A linker provides access to foreign functions from Java code, and access to Java code from foreign functions. *

- * Foreign functions typically reside in libraries that can be loaded on-demand. Each library conforms to + * Foreign functions typically reside in libraries that can be loaded on demand. Each library conforms to * a specific ABI (Application Binary Interface). An ABI is a set of calling conventions and data types associated with * the compiler, OS, and processor where the library was built. For example, a C compiler on Linux/x64 usually * builds libraries that conform to the SystemV ABI. *

* A linker has detailed knowledge of the calling conventions and data types used by a specific ABI. - * For any library which conforms to that ABI, the linker can mediate between Java code running + * For any library that conforms to that ABI, the linker can mediate between Java code running * in the JVM and foreign functions in the library. In particular: *

    *
  • A linker allows Java code to link against foreign functions, via @@ -106,21 +106,21 @@ * of the C function they wish to link against. This description, a {@link FunctionDescriptor function descriptor}, * defines the layouts associated with the parameter types and return type (if any) of the C function. *

    - * Scalar C types such as {@code bool}, {@code int} are modelled as {@linkplain ValueLayout value layouts} + * Scalar C types such as {@code bool}, {@code int} are modeled as {@linkplain ValueLayout value layouts} * of a suitable carrier. The {@linkplain #canonicalLayouts() mapping} between a scalar type and its corresponding * canonical layout is dependent on the ABI implemented by the native linker (see below). *

    - * Composite types are modelled as {@linkplain GroupLayout group layouts}. More specifically, a C {@code struct} type + * Composite types are modeled as {@linkplain GroupLayout group layouts}. More specifically, a C {@code struct} type * maps to a {@linkplain StructLayout struct layout}, whereas a C {@code union} type maps to a {@link UnionLayout union * layout}. When defining a struct or union layout, clients must pay attention to the size and alignment constraint * of the corresponding composite type definition in C. For instance, padding between two struct fields - * must be modelled explicitly, by adding an adequately sized {@linkplain PaddingLayout padding layout} member + * must be modeled explicitly, by adding an adequately sized {@linkplain PaddingLayout padding layout} member * to the resulting struct layout. *

    - * Finally, pointer types such as {@code int**} and {@code int(*)(size_t*, size_t*)} are modelled as + * Finally, pointer types such as {@code int**} and {@code int(*)(size_t*, size_t*)} are modeled as * {@linkplain AddressLayout address layouts}. When the spatial bounds of the pointer type are known statically, * the address layout can be associated with a {@linkplain AddressLayout#targetLayout() target layout}. For instance, - * a pointer that is known to point to a C {@code int[2]} array can be modelled as an address layout whose + * a pointer that is known to point to a C {@code int[2]} array can be modeled as an address layout whose * target layout is a sequence layout whose element count is 2, and whose element type is {@link ValueLayout#JAVA_INT}. *

    * All native linker implementations are guaranteed to provide canonical layouts for the following set of types: @@ -144,11 +144,11 @@ * constant {@link ValueLayout#JAVA_INT} on 32-bit platforms. *

    * A native linker typically does not provide canonical layouts for C's unsigned integral types. Instead, they are - * modelled using the canonical layouts associated with their corresponding signed integral types. For instance, + * modeled using the canonical layouts associated with their corresponding signed integral types. For instance, * the C type {@code unsigned long} maps to the layout constant {@link ValueLayout#JAVA_LONG} on Linux/x64, but maps to * the layout constant {@link ValueLayout#JAVA_INT} on Windows/x64. *

    - * The following table shows some examples of how C types are modelled in Linux/x64 according to the + * The following table shows some examples of how C types are modeled in Linux/x64 according to the * "System V Application Binary Interface" (all the examples provided here will assume these platform-dependent mappings): * *

    @@ -246,7 +246,7 @@ * * Linker implementations may optionally support additional layouts, such as packed struct layouts. * A packed struct is a struct in which there is at least one member layout {@code L} that has an alignment - * constraint less strict than its natural alignment. This allows avoiding padding between member layouts, + * constraint less strict than its natural alignment. This allows to avoid padding between member layouts, * as well as avoiding padding at the end of the struct layout. For example: * {@snippet lang = java: * // No padding between the 2 element layouts: @@ -317,7 +317,7 @@ * as the target layout for the address layouts of both parameters. This will allow the comparator method to access * the contents of the array elements to be compared. We then {@linkplain FunctionDescriptor#toMethodType() turn} * that function descriptor into a suitable {@linkplain java.lang.invoke.MethodType method type} which we then use to look up - * the comparator method handle. We can now create an upcall stub which points to that method, and pass it, as a function + * the comparator method handle. We can now create an upcall stub that points to that method, and pass it, as a function * pointer, to the {@code qsort} downcall handle, as follows: * * {@snippet lang = java: @@ -343,7 +343,7 @@ * void *malloc(size_t size); * } * - * The {@code malloc} function allocates a region of memory of given size, + * The {@code malloc} function allocates a region of memory with the given size, * and returns a pointer to that region of memory, which is later deallocated using another function from * the C standard library: * @@ -415,12 +415,12 @@ * } * * Note how the segment obtained from {@code allocateMemory} acts as any other segment managed by the confined arena. More - * specifically, the obtained segment has the desired size, can only be accessed by a single thread (the thread which created + * specifically, the obtained segment has the desired size, can only be accessed by a single thread (the thread that created * the confined arena), and its lifetime is tied to the surrounding try-with-resources block. * *

    Variadic functions

    * - * Variadic functions are C functions which can accept a variable number and type of arguments. They are declared with a + * Variadic functions are C functions that can accept a variable number and type of arguments. They are declared with a * trailing ellipsis ({@code ...}) at the end of the formal parameter list, such as: {@code void foo(int x, ...);} * The arguments passed in place of the ellipsis are called variadic arguments. Variadic functions are, * essentially, templates that can be specialized into multiple non-variadic functions by replacing the @@ -435,7 +435,7 @@ *
  • {@code float} -> {@code double}
  • * * whereby the signed-ness of the source type corresponds to the signed-ness of the promoted type. The complete process - * of default argument promotion is described in the C specification. In effect these promotions place limits on the + * of default argument promotion is described in the C specification. In effect, these promotions place limits on the * types that can be used to replace the {@code ...}, as the variadic parameters of the specialized form of a variadic * function will always have a promoted type. *

    @@ -503,7 +503,7 @@ * associated with the upcall stub to a type that is incompatible with the type of the upcall stub, and then attempts to * invoke the function through the resulting function pointer. Moreover, if the method * handle associated with an upcall stub returns a {@linkplain MemorySegment memory segment}, clients must ensure - * that this address cannot become invalid after the upcall completes. This can lead to unspecified behavior, + * that this address cannot become invalid after the upcall is completed. This can lead to unspecified behavior, * and even JVM crashes, since an upcall is typically executed in the context of a downcall method handle invocation. * * @implSpec @@ -529,7 +529,7 @@ static Linker nativeLinker() { } /** - * Creates a method handle which is used to call a foreign function with the given signature and address. + * Creates a method handle that is used to call a foreign function with the given signature and address. *

    * Calling this method is equivalent to the following code: * {@snippet lang=java : @@ -553,7 +553,7 @@ static Linker nativeLinker() { MethodHandle downcallHandle(MemorySegment address, FunctionDescriptor function, Option... options); /** - * Creates a method handle which is used to call a foreign function with the given signature. + * Creates a method handle that is used to call a foreign function with the given signature. *

    * The Java {@linkplain java.lang.invoke.MethodType method type} associated with the returned method handle is * {@linkplain FunctionDescriptor#toMethodType() derived} from the argument and return layouts in the function descriptor, @@ -660,7 +660,7 @@ static Linker nativeLinker() { *

    * Each {@link Linker} is responsible for choosing the data types that are widely recognized as useful on the OS * and processor combination supported by the {@link Linker}. Accordingly, the precise set of data type names - * and canonical layouts exposed by the linker is unspecified; it varies from one {@link Linker} to another. + * and canonical layouts exposed by the linker are unspecified; they vary from one {@link Linker} to another. * @implNote It is strongly recommended that the result of {@link #canonicalLayouts()} exposes a set of symbols that is stable over time. * Clients of {@link #canonicalLayouts()} are likely to fail if a data type that was previously exposed by the linker * is no longer exposed, or if its canonical layout is updated. @@ -787,11 +787,11 @@ static StructLayout captureStateLayout() { * A critical function is a function that has an extremely short running time in all cases * (similar to calling an empty function), and does not call back into Java (e.g. using an upcall stub). *

    - * Using this linker option is a hint which some implementations may use to apply + * Using this linker option is a hint that some implementations may use to apply * optimizations that are only valid for critical functions. *

    * Using this linker option when linking non-critical functions is likely to have adverse effects, - * such as loss of performance, or JVM crashes. + * such as loss of performance or JVM crashes. */ static Option critical() { return LinkerOptions.Critical.INSTANCE; diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java index 0f1a6efe826..40014e8c41f 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java @@ -68,7 +68,7 @@ * } TaggedValues[5]; * } * - * The above declaration can be modelled using a layout object, as follows: + * The above declaration can be modeled using a layout object, as follows: * * {@snippet lang=java : * SequenceLayout TAGGED_VALUES = MemoryLayout.sequenceLayout(5, @@ -88,7 +88,7 @@ * associated with the value layout. That is, the constant {@link ValueLayout#JAVA_INT} has carrier {@code int}, and * size of 4 bytes; *

  • The size of an address layout is platform-dependent. That is, the constant {@link ValueLayout#ADDRESS} - * has size of 8 bytes on a 64-bit platform;
  • + * has a size of 8 bytes on a 64-bit platform; *
  • The size of a padding layout is always provided explicitly, on {@linkplain MemoryLayout#paddingLayout(long) construction};
  • *
  • The size of a sequence layout whose element layout is E and element count is L, * is the size of E, multiplied by L;
  • @@ -155,7 +155,7 @@ * } * *

    - * Open path elements also affects the creation of + * Open path elements also affect the creation of * {@linkplain #byteOffsetHandle(PathElement...) offset-computing method handles}. Each open path element becomes * an additional {@code long} parameter in the obtained method handle. This parameter can be used to specify the index * of the sequence element whose offset is to be computed: @@ -185,12 +185,12 @@ * ); * } * - * This layout is a struct layout which describe a rectangle. It contains a single field, namely {@code points}, + * This layout is a struct layout describing a rectangle. It contains a single field, namely {@code points}, * an address layout whose {@linkplain AddressLayout#targetLayout() target layout} is a sequence layout of four * struct layouts. Each struct layout describes a two-dimensional point, and is defined as a pair or * {@link ValueLayout#JAVA_INT} coordinates, with names {@code x} and {@code y}, respectively. *

    - * With dereference path elements, we can obtain a var handle which accesses the {@code y} coordinate of one of the + * With dereference path elements, we can obtain a var handle that accesses the {@code y} coordinate of one of the * point in the rectangle, as follows: * * {@snippet lang=java : @@ -211,7 +211,7 @@ *

    Layout path well-formedness

    * * A layout path is applied to a layout {@code C_0}, also called the initial layout. Each path element in a - * layout path can be thought of as a function which updates the current layout {@code C_i-1} to some other layout + * layout path can be thought of as a function that updates the current layout {@code C_i-1} to some other layout * {@code C_i}. That is, for each path element {@code E1, E2, ... En}, in a layout path {@code P}, we compute * {@code C_i = f_i(C_i-1)}, where {@code f_i} is the selection function associated with the path element under consideration, * denoted as {@code E_i}. The final layout {@code C_i} is also called the selected layout. @@ -278,7 +278,7 @@ *
  • a toplevel variable-length array whose size depends on the value of some unrelated variable, or parameter;
  • *
  • an variable-length array nested in a struct, whose size depends on the value of some other field in the enclosing struct.
  • * - * While variable-length arrays cannot be modelled directly using sequence layouts, clients can still enjoy structured + * While variable-length arrays cannot be modeled directly using sequence layouts, clients can still enjoy structured * access to elements of variable-length arrays using var handles as demonstrated in the following sections. * *

    Toplevel variable-length arrays

    @@ -292,7 +292,7 @@ * } Point; * } * - * In the above code, a point is modelled as two coordinates ({@code x} and {@code y} respectively). Now consider + * In the above code, a point is modeled as two coordinates ({@code x} and {@code y} respectively). Now consider * the following snippet of C code: * * {@snippet lang=c : @@ -303,7 +303,7 @@ * } * } * - * Here, we allocate an array of point ({@code points}). Crucially, the size of the array is dynamically bound to the value + * Here, we allocate an array of points ({@code points}). Crucially, the size of the array is dynamically bound to the value * of the {@code size} variable. Inside the loop, the {@code x} coordinate of all the points in the array is accessed. *

    * To model this code in Java, let's start by defining a layout for the {@code Point} struct, as follows: @@ -353,7 +353,7 @@ * } Polygon; * } * - * In the above code, a polygon is modelled as a size (the number of edges in the polygon) and an array of points + * In the above code, a polygon is modeled as a size (the number of edges in the polygon) and an array of points * (one for each vertex in the polygon). The number of vertices depends on the number of edges in the polygon. As such, * the size of the {@code points} array is left unspecified in the C declaration, using a Flexible Array Member * (a feature standardized in C99). @@ -558,7 +558,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin *

      *
    • If the address layout has a target layout {@code T}, then the size of the returned segment * is {@code T.byteSize()};
    • - *
    • Otherwise, the address layout has no target layout, and the size of the returned segment + *
    • Otherwise, the address layout has no target layout and the size of the returned segment * is zero.
    • *
    * Moreover, if the selected layout is an {@linkplain AddressLayout address layout}, calling {@link VarHandle#set(Object...)} @@ -648,7 +648,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin VarHandle arrayElementVarHandle(PathElement... elements); /** - * Creates a method handle which, given a memory segment, returns a {@linkplain MemorySegment#asSlice(long,long) slice} + * Creates a method handle which, given a memory segment, returns a {@linkplain MemorySegment#asSlice(long, long) slice} * corresponding to the layout selected by the given layout path, where the initial layout in the path is this layout. *

    * The returned method handle has the following characteristics: @@ -670,7 +670,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin * according to the {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout), or * an {@link IllegalArgumentException} will be issued. Note that the alignment constraint of the root layout * can be more strict (but not less) than the alignment constraint of the selected layout. - *

  • The start offset of the slicing operation (computed as above) must fall fall inside the spatial bounds of the + *
  • The start offset of the slicing operation (computed as above) must fall inside the spatial bounds of the * accessed memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case when {@code O + A <= S}, * where {@code O} is the start offset of the slicing operation (computed as above), {@code A} is the size of the * selected layout and {@code S} is the size of the accessed memory segment.
  • @@ -680,7 +680,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin * but more flexibly, as some indices can be specified when invoking the method handle. * * @param elements the layout path elements. - * @return a method handle which is used to slice a memory segment at the offset selected by the given layout path. + * @return a method handle that is used to slice a memory segment at the offset selected by the given layout path. * @throws IllegalArgumentException if the layout path is not well-formed for this layout * @throws IllegalArgumentException if the layout path contains one or more dereference path elements */ @@ -718,14 +718,14 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin sealed interface PathElement permits LayoutPath.PathElementImpl { /** - * Returns a path element which selects a member layout with the given name in a group layout. + * Returns a path element that selects a member layout with the given name in a group layout. * * @implSpec in case multiple group elements with a matching name exist, the path element returned by this - * method will select the first one; that is, the group element with the lowest offset from current path is selected. + * method will select the first one; that is, the group element with the lowest offset from the current path is selected. * In such cases, using {@link #groupElement(long)} might be preferable. * * @param name the name of the member layout to be selected. - * @return a path element which selects the group member layout with the given name. + * @return a path element that selects the group member layout with the given name. */ static PathElement groupElement(String name) { Objects.requireNonNull(name); @@ -734,7 +734,7 @@ static PathElement groupElement(String name) { } /** - * Returns a path element which selects a member layout with the given index in a group layout. + * Returns a path element that selects a member layout with the given index in a group layout. * * @param index the index of the member layout element to be selected. * @return a path element which selects the group member layout with the given index. @@ -749,10 +749,10 @@ static PathElement groupElement(long index) { } /** - * Returns a path element which selects the element layout at the specified position in a sequence layout. + * Returns a path element that selects the element layout at the specified position in a sequence layout. * * @param index the index of the sequence element to be selected. - * @return a path element which selects the sequence element layout with the given index. + * @return a path element that selects the sequence element layout with the given index. * @throws IllegalArgumentException if {@code index < 0} */ static PathElement sequenceElement(long index) { @@ -764,7 +764,7 @@ static PathElement sequenceElement(long index) { } /** - * Returns an open path element which selects the element + * Returns an open path element that selects the element * layout in a range of positions in a sequence layout. The range is expressed as a pair of starting * index (inclusive) {@code S} and step factor (which can also be negative) {@code F}. *

    @@ -777,7 +777,7 @@ static PathElement sequenceElement(long index) { * * @param start the index of the first sequence element to be selected. * @param step the step factor at which subsequence sequence elements are to be selected. - * @return a path element which selects the sequence element layout with the given index. + * @return a path element that selects the sequence element layout with the given index. * @throws IllegalArgumentException if {@code start < 0}, or {@code step == 0} */ static PathElement sequenceElement(long start, long step) { @@ -792,7 +792,7 @@ static PathElement sequenceElement(long start, long step) { } /** - * Returns an open path element which selects an unspecified + * Returns an open path element that selects an unspecified * element layout in a sequence layout. *

    * The exact sequence element selected by this layout is expressed as an index {@code I}. If {@code C} is the @@ -806,10 +806,10 @@ static PathElement sequenceElement() { } /** - * Returns a path element which dereferences an address layout as its + * Returns a path element that dereferences an address layout as its * {@linkplain AddressLayout#targetLayout() target layout} (where set). * - * @return a path element which dereferences an address layout. + * @return a path element that dereferences an address layout. */ static PathElement dereferenceElement() { return new LayoutPath.PathElementImpl(PathKind.DEREF_ELEMENT, @@ -904,7 +904,7 @@ static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayo * structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(2), JAVA_INT); * } * - * Or, alternatively, they can use a member layout which features a smaller alignment constraint. This will result + * Or, alternatively, they can use a member layout that features a smaller alignment constraint. This will result * in a packed struct layout: * * {@snippet lang = java: diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index f145276e814..f01ad657313 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -92,11 +92,11 @@ * a positive number but may be zero, but never negative. *

    * The address and size of a memory segment jointly ensure that access operations on the segment cannot fall - * outside the boundaries of the region of memory which backs the segment. + * outside the boundaries of the region of memory that backs the segment. * That is, a memory segment has spatial bounds. *

    * Every memory segment is associated with a {@linkplain Scope scope}. This ensures that access operations - * on a memory segment cannot occur when the region of memory which backs the memory segment is no longer available + * on a memory segment cannot occur when the region of memory that backs the memory segment is no longer available * (e.g., after the scope associated with the accessed memory segment is no longer {@linkplain Scope#isAlive() alive}). * That is, a memory segment has temporal bounds. *

    @@ -172,7 +172,7 @@ * and its size is 10. As a result, attempting to read an int value at offset 20 of the * {@code slice} segment will result in an exception. The {@linkplain Arena temporal bounds} of the original segment * is inherited by its slices; that is, when the scope associated with {@code segment} is no longer {@linkplain Scope#isAlive() alive}, - * {@code slice} will also be become inaccessible. + * {@code slice} will also become inaccessible. *

    * A client might obtain a {@link Stream} from a segment, which can then be used to slice the segment (according to a given * element layout) and even allow multiple threads to work in parallel on disjoint segment slices @@ -193,7 +193,7 @@ * * Access operations on a memory segment are constrained not only by the spatial and temporal bounds of the segment, * but also by the alignment constraint of the value layout specified to the operation. An access operation can - * access only those offsets in the segment that denote addresses in physical memory which are aligned according + * access only those offsets in the segment that denote addresses in physical memory that are aligned according * to the layout. An address in physical memory is aligned according to a layout if the address is an integer * multiple of the layout's alignment constraint. For example, the address 1000 is aligned according to an 8-byte alignment * constraint (because 1000 is an integer multiple of 8), and to a 4-byte alignment constraint, and to a 2-byte alignment @@ -239,17 +239,17 @@ *

    * The alignment constraint used to access a segment is typically dictated by the shape of the data structure stored * in the segment. For example, if the programmer wishes to store a sequence of 8-byte values in a native segment, then - * the segment should be allocated by specifying a 8-byte alignment constraint, either via {@link Arena#allocate(long, long)} + * the segment should be allocated by specifying an 8-byte alignment constraint, either via {@link Arena#allocate(long, long)} * or {@link Arena#allocate(MemoryLayout)}. These factories ensure that the off-heap region of memory backing * the returned segment has a starting address that is 8-byte aligned. Subsequently, the programmer can access the * segment at the offsets of interest -- 0, 8, 16, 24, etc -- in the knowledge that every such access is aligned. *

    * If the segment being accessed is a heap segment, then determining whether access is aligned is more complex. - * The address of the segment in physical memory is not known, and is not even fixed (it may change when the segment + * The address of the segment in physical memory is not known and is not even fixed (it may change when the segment * is relocated during garbage collection). This means that the address cannot be combined with the specified offset to * determine a target address in physical memory. Since the alignment constraint always refers to alignment of * addresses in physical memory, it is not possible in principle to determine if any offset in a heap segment is aligned. - * For example, suppose the programmer chooses a 8-byte alignment constraint and tries + * For example, suppose the programmer chooses an 8-byte alignment constraint and tries * to access offset 16 in a heap segment. If the heap segment's address 0 corresponds to physical address 1000, * then the target address (1016) would be aligned, but if address 0 corresponds to physical address 1004, * then the target address (1020) would not be aligned. It is undesirable to allow access to target addresses that are @@ -268,7 +268,7 @@ * be accessed at any offset under a 4-byte alignment constraint, because there is no guarantee that the target * address would be 4-byte aligned, e.g., offset 0 would correspond to physical address 1006 while offset 1 would correspond * to physical address 1007. Similarly, the segment cannot be accessed at any offset under an 8-byte alignment constraint, - * because because there is no guarantee that the target address would be 8-byte aligned, e.g., offset 2 would correspond + * because there is no guarantee that the target address would be 8-byte aligned, e.g., offset 2 would correspond * to physical address 1008 but offset 4 would correspond to physical address 1010. *

  • The starting physical address of a {@code long[]} array will be 8-byte aligned (e.g. 1000) on 64-bit platforms, * so that successive long elements occur at 8-byte aligned addresses (e.g., 1000, 1008, 1016, 1024, etc.) On 64-bit platforms, @@ -377,7 +377,7 @@ * to read a pointer from some memory segment. This can be done via the * {@linkplain MemorySegment#get(AddressLayout, long)} access method. This method accepts an * {@linkplain AddressLayout address layout} (e.g. {@link ValueLayout#ADDRESS}), the layout of the pointer - * to be read. For instance on a 64-bit platform, the size of an address layout is 8 bytes. The access operation + * to be read. For instance, on a 64-bit platform, the size of an address layout is 8 bytes. The access operation * also accepts an offset, expressed in bytes, which indicates the position (relative to the start of the memory segment) * at which the pointer is stored. The access operation returns a zero-length native memory segment, backed by a region * of memory whose starting address is the 64-bit value read at the specified offset. @@ -421,7 +421,7 @@ * int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3); // ok *} *

    - * All the methods which can be used to manipulate zero-length memory segments + * All the methods that can be used to manipulate zero-length memory segments * ({@link #reinterpret(long)}, {@link #reinterpret(Arena, Consumer)}, {@link #reinterpret(long, Arena, Consumer)} and * {@link AddressLayout#withTargetLayout(MemoryLayout)}) are * restricted methods, and should be used with caution: @@ -618,7 +618,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * and is accessible from any thread. The size of the segment accepted by the cleanup action is {@link #byteSize()}. * * @apiNote The cleanup action (if present) should take care not to leak the received segment to external - * clients which might access the segment after its backing region of memory is no longer available. Furthermore, + * clients that might access the segment after its backing region of memory is no longer available. Furthermore, * if the provided scope is the scope of an {@linkplain Arena#ofAuto() automatic arena}, the cleanup action * must not prevent the scope from becoming unreachable. * A failure to do so will permanently prevent the regions of memory allocated by the automatic arena from being deallocated. @@ -653,7 +653,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * and is accessible from any thread. The size of the segment accepted by the cleanup action is {@code newSize}. * * @apiNote The cleanup action (if present) should take care not to leak the received segment to external - * clients which might access the segment after its backing region of memory is no longer available. Furthermore, + * clients that might access the segment after its backing region of memory is no longer available. Furthermore, * if the provided scope is the scope of an {@linkplain Arena#ofAuto() automatic arena}, the cleanup action * must not prevent the scope from becoming unreachable. * A failure to do so will permanently prevent the regions of memory allocated by the automatic arena from being deallocated. @@ -661,7 +661,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @param newSize the size of the returned segment. * @param arena the arena to be associated with the returned segment. * @param cleanup the cleanup action that should be executed when the provided arena is closed (can be {@code null}). - * @return a new segment that has the same address as this segment, but with new size and its scope set to + * @return a new segment that has the same address as this segment, but with the new size and its scope set to * that of the provided arena. * @throws UnsupportedOperationException if this segment is not a {@linkplain #isNative() native} segment * @throws IllegalArgumentException if {@code newSize < 0} @@ -690,7 +690,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * Returns {@code true} if this segment is a native segment. A native segment is * created e.g. using the {@link Arena#allocate(long, long)} (and related) factory, or by * {@linkplain #ofBuffer(Buffer) wrapping} a {@linkplain ByteBuffer#allocateDirect(int) direct buffer}. - * @return {@code true} if this segment is native segment. + * @return {@code true} if this segment is a native segment. */ boolean isNative(); @@ -745,7 +745,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { MemorySegment fill(byte value); /** - * Performs a bulk copy from given source segment to this segment. More specifically, the bytes at + * Performs a bulk copy from the given source segment to this segment. More specifically, the bytes at * offset {@code 0} through {@code src.byteSize() - 1} in the source segment are copied into this segment * at offset {@code 0} through {@code src.byteSize() - 1}. *

    @@ -798,14 +798,14 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { long mismatch(MemorySegment other); /** - * Determines whether the contents of this mapped segment is resident in physical + * Determines whether all the contents of this mapped segment are resident in physical * memory. * *

    A return value of {@code true} implies that it is highly likely * that all the data in this segment is resident in physical memory and * may therefore be accessed without incurring any virtual-memory page * faults or I/O operations. A return value of {@code false} does not - * necessarily imply that this segment's content is not resident in physical + * necessarily imply that this segment's contents are not resident in physical * memory. * *

    The returned value is a hint, rather than a guarantee, because the @@ -813,7 +813,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * by the time that an invocation of this method returns.

    * * @return {@code true} if it is likely that the contents of this segment - * is resident in physical memory + * are resident in physical memory * * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -828,7 +828,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * Loads the contents of this mapped segment into physical memory. * *

    This method makes a best effort to ensure that, when it returns, - * this contents of this segment is resident in physical memory. Invoking this + * the contents of this segment are resident in physical memory. Invoking this * method may cause some number of page faults and I/O operations to * occur.

    * @@ -845,7 +845,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * Unloads the contents of this mapped segment from physical memory. * *

    This method makes a best effort to ensure that the contents of this segment are - * are no longer resident in physical memory. Accessing this segment's contents + * no longer resident in physical memory. Accessing this segment's contents * after invoking this method may cause some number of page faults and I/O operations to * occur (as this segment's contents might need to be paged back in).

    * @@ -1029,7 +1029,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * getString(offset, StandardCharsets.UTF_8); *} * - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a Java string constructed from the bytes read from the given starting address up to (but not including) * the first {@code '\0'} terminator character (assuming one is found). * @throws IllegalArgumentException if the size of the string is greater than the largest string @@ -1082,7 +1082,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * {@snippet lang = java: * setString(offset, str, StandardCharsets.UTF_8); *} - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * the final address of this write operation can be expressed as {@code address() + offset}. * @param str the Java string to be written into this segment. * @throws IndexOutOfBoundsException if {@code offset < 0} @@ -1135,13 +1135,13 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { *

    * If the buffer is {@linkplain Buffer#isReadOnly() read-only}, the resulting segment is also * {@linkplain ByteBuffer#isReadOnly() read-only}. Moreover, if the buffer is a {@linkplain Buffer#isDirect() direct buffer}, - * the returned segment is a native segment; otherwise the returned memory segment is a heap segment. + * the returned segment is a native segment; otherwise, the returned memory segment is a heap segment. *

    * If the provided buffer has been obtained by calling {@link #asByteBuffer()} on a memory segment whose * {@linkplain Scope scope} is {@code S}, the returned segment will be associated with the * same scope {@code S}. Otherwise, the scope of the returned segment is an automatic scope that keeps the provided * buffer reachable. As such, if the provided buffer is a direct buffer, its backing memory region will not be - * deallocated as long as the returned segment (or any of its slices) are kept reachable. + * deallocated as long as the returned segment, or any of its slices, are kept reachable. * * @param buffer the buffer instance to be turned into a new memory segment. * @return a memory segment, derived from the given buffer instance. @@ -1244,7 +1244,7 @@ static MemorySegment ofArray(double[] doubleArray) { /** * Creates a zero-length native segment from the given {@linkplain #address() address value}. - * The returned segment is associated with the global scope, and is accessible from any thread. + * The returned segment is associated with the global scope and is accessible from any thread. *

    * On 32-bit platforms, the given address value will be normalized such that the * highest-order ("leftmost") 32 bits of the {@link MemorySegment#address() address} @@ -1309,8 +1309,8 @@ static void copy(MemorySegment srcSegment, long srcOffset, *

    * The copy occurs in an element-wise fashion: the bytes in the source segment are interpreted as a sequence of elements * whose layout is {@code srcElementLayout}, whereas the bytes in the destination segment are interpreted as a sequence of - * elements whose layout is {@code dstElementLayout}. Both element layouts must have same size {@code S}. - * If the byte order of the two element layouts differ, the bytes corresponding to each element to be copied + * elements whose layout is {@code dstElementLayout}. Both element layouts must have the same size {@code S}. + * If the byte order of the two provided element layouts differs, the bytes corresponding to each element to be copied * are swapped accordingly during the copy operation. *

    * If the source segment overlaps with the destination segment, then the copying is performed as if the bytes at @@ -1365,7 +1365,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads a byte from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a byte value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive}. @@ -1381,7 +1381,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes a byte into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the byte value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1398,7 +1398,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads a boolean from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a boolean value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1414,7 +1414,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes a boolean into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the boolean value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive}. @@ -1431,7 +1431,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads a char from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a char value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1447,7 +1447,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes a char into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the char value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1464,7 +1464,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads a short from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a short value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1480,7 +1480,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes a short into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the short value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1497,7 +1497,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads an int from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return an int value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1513,7 +1513,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes an int into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the int value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1530,7 +1530,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads a float from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a float value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1546,7 +1546,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes a float into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the float value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1563,7 +1563,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads a long from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a long value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1579,7 +1579,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes a long into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the long value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1596,7 +1596,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Reads a double from this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a double value read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1612,7 +1612,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes a double into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the double value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1632,7 +1632,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * {@linkplain AddressLayout#targetLayout() target layout} {@code T}, then the size of the returned segment * is set to {@code T.byteSize()}. * @param layout the layout of the region of memory to be read. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @return a native segment wrapping an address read from this segment. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -1651,7 +1651,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * Writes an address into this segment at the given offset, with the given layout. * * @param layout the layout of the region of memory to be written. - * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param offset the offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the address value to be written. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive} @@ -2181,8 +2181,8 @@ static long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOff * for equality. That is, two scopes are considered {@linkplain #equals(Object) equal} if they denote the same lifetime. *

    * The lifetime of a memory segment can be either unbounded or bounded. An unbounded lifetime - * is modelled with the global scope. The global scope is always {@link #isAlive() alive}. As such, a segment - * associated with the global scope features trivial temporal bounds, and is always accessible. + * is modeled with the global scope. The global scope is always {@link #isAlive() alive}. As such, a segment + * associated with the global scope features trivial temporal bounds and is always accessible. * Segments associated with the global scope are: *

      *
    • Segments obtained from the {@linkplain Arena#global() global arena};
    • @@ -2190,7 +2190,7 @@ static long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOff *
    • Zero-length memory segments.
    • *
    *

    - * Conversely, a bounded lifetime is modelled with a segment scope that can be invalidated, either {@link Arena#close() explicitly}, + * Conversely, a bounded lifetime is modeled with a segment scope that can be invalidated, either {@link Arena#close() explicitly}, * or automatically, by the garbage collector. A segment scope that is invalidated automatically is an automatic scope. * An automatic scope is always {@link #isAlive() alive} as long as it is reachable. * Segments associated with an automatic scope are: @@ -2219,7 +2219,7 @@ sealed interface Scope permits MemorySessionImpl { /** * {@return {@code true}, if the provided object is also a scope, which models the same lifetime as that - * modelled by this scope}. In that case, it is always the case that + * modeled by this scope}. In that case, it is always the case that * {@code this.isAlive() == ((Scope)that).isAlive()}. * @param that the object to be tested. */ diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java index 0c73f9b904c..fa43a9252bc 100644 --- a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java +++ b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java @@ -346,7 +346,7 @@ default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) { * The contents of the source segment is copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * MemorySegment dest = this.allocate(elementLayout, elementCount); * MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount); @@ -389,7 +389,7 @@ default MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment sour * The contents of the source array is copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * this.allocateFrom(layout, MemorySegment.ofArray(array), * ValueLayout.JAVA_BYTE, 0, array.length) @@ -408,10 +408,10 @@ default MemorySegment allocateFrom(ValueLayout.OfByte elementLayout, byte... ele * {@return a new memory segment initialized with the elements in the provided short array.} *

    * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. - * The contents of the source array is copied into the result segment element by element, according to the byte + * The contents of the source array are copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * this.allocateFrom(layout, MemorySegment.ofArray(array), * ValueLayout.JAVA_SHORT, 0, array.length) @@ -433,7 +433,7 @@ default MemorySegment allocateFrom(ValueLayout.OfShort elementLayout, short... e * The contents of the source array is copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * this.allocateFrom(layout, MemorySegment.ofArray(array), * ValueLayout.JAVA_CHAR, 0, array.length) @@ -455,7 +455,7 @@ default MemorySegment allocateFrom(ValueLayout.OfChar elementLayout, char... ele * The contents of the source array is copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * this.allocateFrom(layout, MemorySegment.ofArray(array), * ValueLayout.JAVA_INT, 0, array.length) @@ -477,7 +477,7 @@ default MemorySegment allocateFrom(ValueLayout.OfInt elementLayout, int... eleme * The contents of the source array is copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * this.allocateFrom(layout, MemorySegment.ofArray(array), * ValueLayout.JAVA_FLOAT, 0, array.length) @@ -499,7 +499,7 @@ default MemorySegment allocateFrom(ValueLayout.OfFloat elementLayout, float... e * The contents of the source array is copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * this.allocateFrom(layout, MemorySegment.ofArray(array), * ValueLayout.JAVA_LONG, 0, array.length) @@ -521,7 +521,7 @@ default MemorySegment allocateFrom(ValueLayout.OfLong elementLayout, long... ele * The contents of the source array is copied into the result segment element by element, according to the byte * order and alignment constraint of the given element layout. * - * @implSpec the default implementation for this method is equivalent to the following code: + * @implSpec The default implementation for this method is equivalent to the following code: * {@snippet lang = java: * this.allocateFrom(layout, MemorySegment.ofArray(array), * ValueLayout.JAVA_DOUBLE, 0, array.length) @@ -592,7 +592,7 @@ default MemorySegment allocate(long byteSize) { MemorySegment allocate(long byteSize, long byteAlignment); /** - * Returns a segment allocator which responds to allocation requests by returning consecutive slices + * Returns a segment allocator that responds to allocation requests by returning consecutive slices * obtained from the provided segment. Each new allocation request will return a new slice starting at the * current offset (modulo additional padding to satisfy alignment constraint), with given size. *

    @@ -601,7 +601,7 @@ default MemorySegment allocate(long byteSize) { * * @implNote A slicing allocator is not thread-safe. * - * @param segment the segment which the returned allocator should slice from. + * @param segment the segment from which the returned allocator should slice from. * @return a new slicing allocator */ static SegmentAllocator slicingAllocator(MemorySegment segment) { @@ -610,7 +610,7 @@ static SegmentAllocator slicingAllocator(MemorySegment segment) { } /** - * Returns a segment allocator which responds to allocation requests by recycling a single segment. Each + * Returns a segment allocator that responds to allocation requests by recycling a single segment. Each * new allocation request will return a new slice starting at the segment offset {@code 0}, hence the name * prefix allocator. * Equivalent to (but likely more efficient than) the following code: @@ -628,7 +628,7 @@ static SegmentAllocator slicingAllocator(MemorySegment segment) { * allocator might cause a thread to overwrite contents written to the underlying segment by a different thread. * * @param segment the memory segment to be recycled by the returned allocator. - * @return an allocator which recycles an existing segment upon each new allocation request. + * @return an allocator that recycles an existing segment upon each new allocation request. */ static SegmentAllocator prefixAllocator(MemorySegment segment) { return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment); diff --git a/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java b/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java index 953d1cd0278..82a08938c4d 100644 --- a/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java @@ -89,7 +89,7 @@ public sealed interface SequenceLayout extends MemoryLayout permits SequenceLayo * var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT)); * } *

    - * If one of the provided element count is the special value {@code -1}, then the element + * If one of the provided element counts is the special value {@code -1}, then the element * count in that position will be inferred from the remaining element counts and the * element count of the flattened projection of this layout. For instance, a layout equivalent to * the above {@code reshapeSeq} can also be computed in the following ways: diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java index 4af2076fb5f..127a5f5d446 100644 --- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java +++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java @@ -49,7 +49,7 @@ * A symbol lookup is created with respect to a particular library (or libraries). Subsequently, the {@link SymbolLookup#find(String)} * method takes the name of a symbol and returns the address of the symbol in that library. *

    - * The address of a symbol is modelled as a zero-length {@linkplain MemorySegment memory segment}. The segment can be used in different ways: + * The address of a symbol is modeled as a zero-length {@linkplain MemorySegment memory segment}. The segment can be used in different ways: *

      *
    • It can be passed to a {@link Linker} to create a downcall method handle, which can then be used to call the foreign function at the segment's address.
    • *
    • It can be passed to an existing {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handle}, as an argument to the underlying foreign function.
    • @@ -132,7 +132,7 @@ public interface SymbolLookup { Optional find(String name); /** - * {@return a composed symbol lookup that returns result of finding the symbol with this lookup if found, + * {@return a composed symbol lookup that returns the result of finding the symbol with this lookup if found, * otherwise returns the result of finding the symbol with the other lookup} * * @apiNote This method could be used to chain multiple symbol lookups together, e.g. so that symbols could @@ -143,7 +143,7 @@ public interface SymbolLookup { * .or(SymbolLookup.loaderLookup()); *} * The above code creates a symbol lookup that first searches for symbols in the "foo" library. If no symbol is found - * in "foo" then "bar" is searched. Finally, if a symbol is not found in neither "foo" nor "bar", the {@linkplain + * in "foo" then "bar" is searched. Finally, if a symbol is neither found in "foo" nor in "bar", the {@linkplain * SymbolLookup#loaderLookup() loader lookup} is used. * * @param other the symbol lookup that should be used to look for symbols not found in this lookup. diff --git a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java index 00f6541f133..ff2cd290388 100644 --- a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java @@ -30,7 +30,7 @@ import jdk.internal.foreign.layout.ValueLayouts; /** - * A layout that models values of basic data types. Examples of values modelled by a value layout are + * A layout that models values of basic data types. Examples of values modeled by a value layout are * integral values (either signed or unsigned), floating-point values and * address values. *

      @@ -42,7 +42,7 @@ * @apiNote Some characteristics of the Java layout constants are platform-dependent. For instance, the byte order of * these constants is set to the {@linkplain ByteOrder#nativeOrder() native byte order}, thus making it easy to work * with other APIs, such as arrays and {@link java.nio.ByteBuffer}. Moreover, the alignment constraint of - * {@link ValueLayout#JAVA_LONG} and {@link ValueLayout#JAVA_DOUBLE} is set to 8 bytes on 64-bit platforms, but only to + * {@link ValueLayout#JAVA_LONG} and {@link ValueLayout#JAVA_DOUBLE} are set to 8 bytes on 64-bit platforms, but only to * 4 bytes on 32-bit platforms. * * @implSpec implementing classes and subclasses are immutable, thread-safe and value-based. @@ -102,7 +102,7 @@ public sealed interface ValueLayout extends MemoryLayout permits * The returned var handle checks that accesses are aligned according to this value layout's * {@linkplain MemoryLayout#byteAlignment() alignment constraint}. * - * @apiNote This method is similar, but more efficient, than calling {@code MemoryLayout#varHandle(PathElement...)} + * @apiNote This method is similar, but more efficient than calling {@code MemoryLayout#varHandle(PathElement...)} * with an empty path element array, as it avoids the creation of the var args array. * * @apiNote The returned var handle features certain access mode diff --git a/src/java.base/share/classes/java/lang/foreign/package-info.java b/src/java.base/share/classes/java/lang/foreign/package-info.java index a427ccf371f..bf505284cef 100644 --- a/src/java.base/share/classes/java/lang/foreign/package-info.java +++ b/src/java.base/share/classes/java/lang/foreign/package-info.java @@ -33,7 +33,7 @@ * models a contiguous region of memory, residing either inside or outside the Java heap. Memory segments are * typically allocated using an {@link java.lang.foreign.Arena}, which controls the lifetime of the regions of memory * backing the segments it allocates. The contents of a memory segment can be described using a - * {@link java.lang.foreign.MemoryLayout memory layout}, which provides basic operations to query sizes, offsets and + * {@link java.lang.foreign.MemoryLayout memory layout}, which provides basic operations to query sizes, offsets, and * alignment constraints. Memory layouts also provide an alternate, more abstract way, to * access memory segments using * {@linkplain java.lang.foreign.MemoryLayout#varHandle(java.lang.foreign.MemoryLayout.PathElement...) var handles}, @@ -61,7 +61,7 @@ * in Section {@jls 14.20.3} of The Java Language Specification. *

      * Memory segments provide strong safety guarantees when it comes to memory access. First, when accessing a memory segment, - * the access coordinates are validated (upon access), to make sure that access does not occur at any address which resides + * the access coordinates are validated (upon access), to make sure that access does not occur at any address that resides * outside the boundaries of the memory segment used by the access operation. We call this guarantee spatial safety; * in other words, access to memory segments is bounds-checked, in the same way as array access is, as described in * Section {@jls 15.10.4} of The Java Language Specification. @@ -121,14 +121,14 @@ *

      * Binding foreign data and/or functions is generally unsafe and, if done incorrectly, can result in VM crashes, * or memory corruption when the bound Java API element is accessed. For instance, incorrectly resizing a native - * memory sgement using {@link java.lang.foreign.MemorySegment#reinterpret(long)} can lead to a JVM crash, or, worse, + * memory segment using {@link java.lang.foreign.MemorySegment#reinterpret(long)} can lead to a JVM crash, or, worse, * lead to silent memory corruption when attempting to access the resized segment. For these reasons, it is crucial for * code that calls a restricted method to never pass arguments that might cause incorrect binding of foreign data and/or * functions to a Java API. *

      * Given the potential danger of restricted methods, the Java runtime issues a warning on the standard error stream * every time a restricted method is invoked. Such warnings can be disabled by granting access to restricted methods - * to selected modules. This can be done either via implementation-specific command line options, or programmatically, e.g. by calling + * to selected modules. This can be done either via implementation-specific command line options or programmatically, e.g. by calling * {@link java.lang.ModuleLayer.Controller#enableNativeAccess(java.lang.Module)}. *

      * For every class in this package, unless specified otherwise, any method arguments of reference @@ -142,7 +142,7 @@ * In the reference implementation, access to restricted methods can be granted to specific modules using the command line option * {@code --enable-native-access=M1,M2, ... Mn}, where {@code M1}, {@code M2}, {@code ... Mn} are module names * (for the unnamed module, the special value {@code ALL-UNNAMED} can be used). If this option is specified, access to - * restricted methods is only granted to the modules listed by that option. If this option is not specified, + * restricted methods are only granted to the modules listed by that option. If this option is not specified, * access to restricted methods is enabled for all modules, but access to restricted methods will result in runtime warnings. * * @spec jni/index.html Java Native Interface Specification From 348903b8000670df674f605d8a789dd4ad723510 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 7 Nov 2023 15:05:03 +0000 Subject: [PATCH 22/31] 8319560: Reformat method parameters in the FFM API Reviewed-by: mcimadamore --- .../share/classes/java/lang/foreign/Linker.java | 9 +++++++-- .../classes/java/lang/foreign/MemorySegment.java | 16 +++++++++------- .../java/lang/foreign/SegmentAllocator.java | 7 +++++-- .../classes/java/lang/foreign/SymbolLookup.java | 6 +++++- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index 53fe45d81f3..604b1489239 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -550,7 +550,9 @@ static Linker nativeLinker() { */ @CallerSensitive @Restricted - MethodHandle downcallHandle(MemorySegment address, FunctionDescriptor function, Option... options); + MethodHandle downcallHandle(MemorySegment address, + FunctionDescriptor function, + Option... options); /** * Creates a method handle that is used to call a foreign function with the given signature. @@ -637,7 +639,10 @@ static Linker nativeLinker() { */ @CallerSensitive @Restricted - MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function, Arena arena, Linker.Option... options); + MemorySegment upcallStub(MethodHandle target, + FunctionDescriptor function, + Arena arena, + Linker.Option... options); /** * Returns a symbol lookup for symbols in a set of commonly used libraries. diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index f01ad657313..ad00dbe11b1 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -670,7 +670,9 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { */ @CallerSensitive @Restricted - MemorySegment reinterpret(long newSize, Arena arena, Consumer cleanup); + MemorySegment reinterpret(long newSize, + Arena arena, + Consumer cleanup); /** * {@return {@code true}, if this segment is read-only} @@ -2081,9 +2083,9 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IndexOutOfBoundsException if either {@code srcOffset}, {@code dstIndex} or {@code elementCount} are {@code < 0} */ @ForceInline - static void copy( - MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset, - Object dstArray, int dstIndex, int elementCount) { + static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset, + Object dstArray, int dstIndex, + int elementCount) { Objects.requireNonNull(srcSegment); Objects.requireNonNull(dstArray); Objects.requireNonNull(srcLayout); @@ -2121,9 +2123,9 @@ static void copy( * @throws IndexOutOfBoundsException if either {@code srcIndex}, {@code dstOffset} or {@code elementCount} are {@code < 0} */ @ForceInline - static void copy( - Object srcArray, int srcIndex, - MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset, int elementCount) { + static void copy(Object srcArray, int srcIndex, + MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset, + int elementCount) { Objects.requireNonNull(srcArray); Objects.requireNonNull(dstSegment); Objects.requireNonNull(dstLayout); diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java index fa43a9252bc..318f44eb822 100644 --- a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java +++ b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java @@ -372,8 +372,11 @@ default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) { * @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0} */ @ForceInline - default MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source, - ValueLayout sourceElementLayout, long sourceOffset, long elementCount) { + default MemorySegment allocateFrom(ValueLayout elementLayout, + MemorySegment source, + ValueLayout sourceElementLayout, + long sourceOffset, + long elementCount) { Objects.requireNonNull(source); Objects.requireNonNull(sourceElementLayout); Objects.requireNonNull(elementLayout); diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java index 127a5f5d446..fa694b4ee7d 100644 --- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java +++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java @@ -262,7 +262,11 @@ static SymbolLookup libraryLookup(Path path, Arena arena) { return libraryLookup(path, RawNativeLibraries::load, arena); } - private static SymbolLookup libraryLookup(Z libDesc, BiFunction loadLibraryFunc, Arena libArena) { + private static + SymbolLookup libraryLookup(Z libDesc, + BiFunction loadLibraryFunc, + Arena libArena) { + Objects.requireNonNull(libDesc); Objects.requireNonNull(libArena); // attempt to load native library from path or name From 01bf865c145ecd61be50bb6209a2f12784f66761 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Tue, 7 Nov 2023 15:07:17 +0000 Subject: [PATCH 23/31] 8317937: @sealedGraph: Links to inner classes fails in links Reviewed-by: pminborg --- .../src/classes/build/tools/taglet/SealedGraph.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java index 787789fa0d0..fd1b73355b3 100644 --- a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java +++ b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java @@ -229,7 +229,7 @@ private String relativeLink(TypeElement node) { var forwardNavigator = nodePackage.getQualifiedName().toString() .replace(".", "/"); - return backNavigator + forwardNavigator + "/" + node.getSimpleName() + ".html"; + return backNavigator + forwardNavigator + "/" + packagelessCanonicalName(node) + ".html"; } public void addEdge(TypeElement node, TypeElement subNode) { @@ -315,5 +315,14 @@ private static Optional packageName(TypeElement element) { case MEMBER -> packageName((TypeElement) element.getEnclosingElement()); }; } + + private static String packagelessCanonicalName(TypeElement element) { + String result = element.getSimpleName().toString(); + while (element.getNestingKind() == NestingKind.MEMBER) { + element = (TypeElement) element.getEnclosingElement(); + result = element.getSimpleName().toString() + '.' + result; + } + return result; + } } } From 481896f4bc4f579d5b69568e6fd1a46b12f15e6e Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 7 Nov 2023 15:27:48 +0000 Subject: [PATCH 24/31] 8319532: jshell - Non-sealed declarations sometimes break a snippet evaluation Reviewed-by: asotona --- .../classes/jdk/jshell/CompletenessAnalyzer.java | 2 +- test/langtools/jdk/jshell/ClassesTest.java | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java index dc8cff8c243..1579a48786c 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java @@ -306,7 +306,7 @@ static enum TK { AMPAMP(TokenKind.AMPAMP, XEXPR, true), // && BARBAR(TokenKind.BARBAR, XEXPR, true), // || PLUS(TokenKind.PLUS, XEXPR1, true), // + - SUB(TokenKind.SUB, XEXPR1, true), // - + SUB(TokenKind.SUB, XEXPR1 | XDECL, true), // - SLASH(TokenKind.SLASH, XEXPR, true), // / BAR(TokenKind.BAR, XEXPR, true), // | CARET(TokenKind.CARET, XEXPR, true), // ^ diff --git a/test/langtools/jdk/jshell/ClassesTest.java b/test/langtools/jdk/jshell/ClassesTest.java index eafd2320db0..8c17c8072f8 100644 --- a/test/langtools/jdk/jshell/ClassesTest.java +++ b/test/langtools/jdk/jshell/ClassesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8145239 8129559 8080354 8189248 8010319 8246353 8247456 8282160 8292755 + * @bug 8145239 8129559 8080354 8189248 8010319 8246353 8247456 8282160 8292755 8319532 * @summary Tests for EvaluationState.classes * @build KullaTesting TestingInputStream ExpectedDiagnostic * @run testng ClassesTest @@ -374,4 +374,11 @@ public void run() { """); } + public void testNonSealed() { + assertAnalyze("non-sealed class C extends B {}int i;", + "non-sealed class C extends B {}", + "int i;", + true); + } + } From e56c0a5c0d33c34c832e59b41482cfb81a26e62a Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Tue, 7 Nov 2023 16:52:22 +0000 Subject: [PATCH 25/31] 8314891: Additional Zip64 extra header validation Reviewed-by: coffeys --- .../share/classes/java/util/zip/ZipFile.java | 109 ++- .../classes/jdk/nio/zipfs/ZipFileSystem.java | 231 +++-- .../zip/ZipFile/MissingZIP64EntriesTest.java | 816 ++++++++++++++++++ 3 files changed, 1071 insertions(+), 85 deletions(-) create mode 100644 test/jdk/java/util/zip/ZipFile/MissingZIP64EntriesTest.java diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index bbcd3cdd712..b7b15d7de0f 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -1220,17 +1220,23 @@ private int checkAndAddEntry(int pos, int index) } int entryPos = pos + CENHDR; int nlen = CENNAM(cen, pos); + int elen = CENEXT(cen, pos); + int clen = CENCOM(cen, pos); if (entryPos + nlen > cen.length - ENDHDR) { zerror("invalid CEN header (bad header size)"); } - int elen = CENEXT(cen, pos); if (elen > 0 && !DISABLE_ZIP64_EXTRA_VALIDATION) { long extraStartingOffset = pos + CENHDR + nlen; if ((int)extraStartingOffset != extraStartingOffset) { zerror("invalid CEN header (bad extra offset)"); } checkExtraFields(pos, (int)extraStartingOffset, elen); + } else if (elen == 0 && (CENSIZ(cen, pos) == ZIP64_MAGICVAL + || CENLEN(cen, pos) == ZIP64_MAGICVAL + || CENOFF(cen, pos) == ZIP64_MAGICVAL + || CENDSK(cen, pos) == ZIP64_MAGICCOUNT)) { + zerror("Invalid CEN header (invalid zip64 extra len size)"); } try { @@ -1243,10 +1249,9 @@ private int checkAndAddEntry(int pos, int index) entries[index++] = hash; entries[index++] = next; entries[index ] = pos; - // Validate comment if it exists - // if the bytes representing the comment cannot be converted to + // Validate comment if it exists. + // If the bytes representing the comment cannot be converted to // a String via zcp.toString, an Exception will be thrown - int clen = CENCOM(cen, pos); if (clen > 0) { int start = entryPos + nlen + elen; zcp.toString(cen, start, clen); @@ -1259,6 +1264,7 @@ private int checkAndAddEntry(int pos, int index) /** * Validate the Zip64 Extra block fields + * @param cenPos The CEN offset for the current Entry * @param startingOffset Extra Field starting offset within the CEN * @param extraFieldLen Length of this Extra field * @throws ZipException If an error occurs validating the Zip64 Extra @@ -1273,7 +1279,7 @@ private void checkExtraFields(int cenPos, int startingOffset, } // CEN Offset where this Extra field ends int extraEndOffset = startingOffset + extraFieldLen; - if (extraEndOffset > cen.length) { + if (extraEndOffset > cen.length - ENDHDR) { zerror("Invalid CEN header (extra data field size too long)"); } int currentOffset = startingOffset; @@ -1302,9 +1308,13 @@ private void checkExtraFields(int cenPos, int startingOffset, long csize = CENSIZ(cen, cenPos); // Get the uncompressed size; long size = CENLEN(cen, cenPos); + // Get the LOC offset + long locoff = CENOFF(cen, cenPos); + // Get the Disk Number + int diskNo = CENDSK(cen, cenPos); checkZip64ExtraFieldValues(currentOffset, tagBlockSize, - csize, size); + csize, size, locoff, diskNo); } currentOffset += tagBlockSize; } @@ -1312,25 +1322,29 @@ private void checkExtraFields(int cenPos, int startingOffset, /** * Validate the Zip64 Extended Information Extra Field (0x0001) block - * size and that the uncompressed size and compressed size field - * values are not negative. - * Note: As we do not use the LOC offset or Starting disk number - * field value we will not validate them + * size; that the uncompressed size, compressed size field and LOC + * offset fields are not negative. Also make sure the field exists if + * the CEN header field is set to 0xFFFFFFFF. + * Note: As we do not use the Starting disk number field, + * we will not validate its value * @param off the starting offset for the Zip64 field value * @param blockSize the size of the Zip64 Extended Extra Field * @param csize CEN header compressed size value * @param size CEN header uncompressed size value + * @param locoff CEN header LOC offset + * @param diskNo CEN header Disk number * @throws ZipException if an error occurs */ private void checkZip64ExtraFieldValues(int off, int blockSize, long csize, - long size) + long size, long locoff, int diskNo) throws ZipException { byte[] cen = this.cen; // if ZIP64_EXTID blocksize == 0, which may occur with some older // versions of Apache Ant and Commons Compress, validate csize and size // to make sure neither field == ZIP64_MAGICVAL if (blockSize == 0) { - if (csize == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL) { + if (csize == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL || + locoff == ZIP64_MAGICVAL || diskNo == ZIP64_MAGICCOUNT) { zerror("Invalid CEN header (invalid zip64 extra data field size)"); } // Only validate the ZIP64_EXTID data if the block size > 0 @@ -1338,22 +1352,45 @@ private void checkZip64ExtraFieldValues(int off, int blockSize, long csize, } // Validate the Zip64 Extended Information Extra Field (0x0001) // length. - if (!isZip64ExtBlockSizeValid(blockSize)) { + if (!isZip64ExtBlockSizeValid(blockSize, csize, size, locoff, diskNo)) { zerror("Invalid CEN header (invalid zip64 extra data field size)"); } // Check the uncompressed size is not negative - // Note we do not need to check blockSize is >= 8 as - // we know its length is at least 8 from the call to - // isZip64ExtBlockSizeValid() - if ((size == ZIP64_MAGICVAL)) { - if(get64(cen, off) < 0) { - zerror("Invalid zip64 extra block size value"); + if (size == ZIP64_MAGICVAL) { + if ( blockSize >= Long.BYTES) { + if (get64(cen, off) < 0) { + zerror("Invalid zip64 extra block size value"); + } + off += Long.BYTES; + blockSize -= Long.BYTES; + } else { + zerror("Invalid Zip64 extra block, missing size"); } } // Check the compressed size is not negative - if ((csize == ZIP64_MAGICVAL) && (blockSize >= 16)) { - if (get64(cen, off + 8) < 0) { - zerror("Invalid zip64 extra block compressed size value"); + if (csize == ZIP64_MAGICVAL) { + if (blockSize >= Long.BYTES) { + if (get64(cen, off) < 0) { + zerror("Invalid zip64 extra block compressed size value"); + } + off += Long.BYTES; + blockSize -= Long.BYTES; + } else { + zerror("Invalid Zip64 extra block, missing compressed size"); + } + } + // Check the LOC offset is not negative + if (locoff == ZIP64_MAGICVAL) { + if (blockSize >= Long.BYTES) { + if (get64(cen, off) < 0) { + zerror("Invalid zip64 extra block LOC OFFSET value"); + } + // Note: We do not need to adjust the following fields as + // this is the last field we are leveraging + // off += Long.BYTES; + // blockSize -= Long.BYTES; + } else { + zerror("Invalid Zip64 extra block, missing LOC offset value"); } } } @@ -1370,22 +1407,22 @@ private void checkZip64ExtraFieldValues(int off, int blockSize, long csize, * See PKWare APP.Note Section 4.5.3 for more details * * @param blockSize the Zip64 Extended Information Extra Field size + * @param csize CEN header compressed size value + * @param size CEN header uncompressed size value + * @param locoff CEN header LOC offset + * @param diskNo CEN header Disk number * @return true if the extra block size is valid; false otherwise */ - private static boolean isZip64ExtBlockSizeValid(int blockSize) { - /* - * As the fields must appear in order, the block size indicates which - * fields to expect: - * 8 - uncompressed size - * 16 - uncompressed size, compressed size - * 24 - uncompressed size, compressed sise, LOC Header offset - * 28 - uncompressed size, compressed sise, LOC Header offset, - * and Disk start number - */ - return switch(blockSize) { - case 8, 16, 24, 28 -> true; - default -> false; - }; + private static boolean isZip64ExtBlockSizeValid(int blockSize, long csize, + long size, long locoff, + int diskNo) { + int expectedBlockSize = + (csize == ZIP64_MAGICVAL ? Long.BYTES : 0) + + (size == ZIP64_MAGICVAL ? Long.BYTES : 0) + + (locoff == ZIP64_MAGICVAL ? Long.BYTES : 0) + + (diskNo == ZIP64_MAGICCOUNT ? Integer.BYTES : 0); + return expectedBlockSize == blockSize; + } private int getEntryHash(int index) { return entries[index]; } private int getEntryNext(int index) { return entries[index + 1]; } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 0ee156f03f0..1b1009f1886 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1583,6 +1583,10 @@ private byte[] initCEN() throws IOException { int elen = CENEXT(cen, pos); int clen = CENCOM(cen, pos); int flag = CENFLG(cen, pos); + long csize = CENSIZ(cen, pos); + long size = CENLEN(cen, pos); + long locoff = CENOFF(cen, pos); + int diskNo = CENDSK(cen, pos); if ((flag & 1) != 0) { throw new ZipException("invalid CEN header (encrypted entry)"); } @@ -1592,6 +1596,13 @@ private byte[] initCEN() throws IOException { if (pos + CENHDR + nlen > limit) { throw new ZipException("invalid CEN header (bad header size)"); } + if (elen > 0) { + checkExtraFields(cen, pos, size, csize, locoff, diskNo, + pos + CENHDR + nlen, elen); + } else if (elen == 0 && (size == ZIP64_MINVAL || csize == ZIP64_MINVAL || + locoff == ZIP64_MINVAL || diskNo == ZIP64_MINVAL32)) { + throw new ZipException("Invalid CEN header (invalid zip64 extra len size)"); + } IndexNode inode = new IndexNode(cen, pos, nlen); if (inode.pathHasDotOrDotDot()) { throw new ZipException("ZIP file can't be opened as a file system " + @@ -1613,6 +1624,165 @@ private byte[] initCEN() throws IOException { return cen; } + /** + * Validate the Zip64 Extra block fields + * @param cen CEN array + * @param cenPos starting offset in the CEN for the Extra field + * @param size CEN size value + * @param csize CEN csize value + * @param locoff CEN LOC offset value + * @param diskNo CEN Disk number value + * @param startingOffset Extra Field starting offset within the CEN + * @param extraFieldLen Length of this Extra field + * @throws ZipException If an error occurs validating the Zip64 Extra + * block + */ + private void checkExtraFields( byte[] cen, int cenPos, long size, long csize, + long locoff, int diskNo, int startingOffset, + int extraFieldLen) throws ZipException { + // Extra field Length cannot exceed 65,535 bytes per the PKWare + // APP.note 4.4.11 + if (extraFieldLen > 0xFFFF) { + zerror("invalid extra field length"); + } + // CEN Offset where this Extra field ends + int extraEndOffset = startingOffset + extraFieldLen; + if (extraEndOffset > cen.length - ENDHDR) { + zerror("Invalid CEN header (extra data field size too long)"); + } + int currentOffset = startingOffset; + // Walk through each Extra Header. Each Extra Header Must consist of: + // Header ID - 2 bytes + // Data Size - 2 bytes: + while (currentOffset + Integer.BYTES <= extraEndOffset) { + int tag = SH(cen, currentOffset); + currentOffset += Short.BYTES; + + int tagBlockSize = SH(cen, currentOffset); + currentOffset += Short.BYTES; + int tagBlockEndingOffset = currentOffset + tagBlockSize; + + // The ending offset for this tag block should not go past the + // offset for the end of the extra field + if (tagBlockEndingOffset > extraEndOffset) { + zerror(String.format( + "Invalid CEN header (invalid extra data field size for " + + "tag: 0x%04x at %d)", + tag, cenPos)); + } + + if (tag == EXTID_ZIP64) { + checkZip64ExtraFieldValues(cen, currentOffset, tagBlockSize, + csize, size, locoff, diskNo); + } + currentOffset += tagBlockSize; + } + } + + /** + * Validate the Zip64 Extended Information Extra Field (0x0001) block + * size; that the uncompressed size, compressed size field and LOC + * offset fields are not negative. Also make sure the field exists if + * the CEN header field is set to 0xFFFFFFFF. + * Note: As we do not use the Starting disk number field, + * we will not validate its value + * @param cen CEN array + * @param off the starting offset for the Zip64 field value + * @param blockSize the size of the Zip64 Extended Extra Field + * @param csize CEN header compressed size value + * @param size CEN header uncompressed size value + * @param locoff CEN header LOC offset + * @param diskNo CEN header Disk Number + * @throws ZipException if an error occurs + */ + private void checkZip64ExtraFieldValues(byte[] cen, int off, int blockSize, long csize, + long size, long locoff, int diskNo) + throws ZipException { + // if ZIP64_EXTID blocksize == 0, which may occur with some older + // versions of Apache Ant and Commons Compress, validate csize and size + // to make sure neither field == ZIP64_MAGICVAL + if (blockSize == 0) { + if (csize == ZIP64_MINVAL || size == ZIP64_MINVAL || + locoff == ZIP64_MINVAL || diskNo == ZIP64_MINVAL32) { + zerror("Invalid CEN header (invalid zip64 extra data field size)"); + } + // Only validate the ZIP64_EXTID data if the block size > 0 + return; + } + // Validate the Zip64 Extended Information Extra Field (0x0001) + // length. + if (!isZip64ExtBlockSizeValid(blockSize, csize, size, locoff, diskNo)) { + zerror("Invalid CEN header (invalid zip64 extra data field size)"); + } + // Check the uncompressed size is not negative + if (size == ZIP64_MINVAL) { + if (blockSize >= Long.BYTES) { + if (LL(cen, off) < 0) { + zerror("Invalid zip64 extra block size value"); + } + off += Long.BYTES; + blockSize -= Long.BYTES; + } else { + zerror("Invalid Zip64 extra block, missing size"); + } + } + // Check the compressed size is not negative + if (csize == ZIP64_MINVAL) { + if (blockSize >= Long.BYTES) { + if (LL(cen, off) < 0) { + zerror("Invalid zip64 extra block compressed size value"); + } + off += Long.BYTES; + blockSize -= Long.BYTES; + } else { + zerror("Invalid Zip64 extra block, missing compressed size"); + } + } + // Check the LOC offset is not negative + if (locoff == ZIP64_MINVAL) { + if (blockSize >= Long.BYTES) { + if (LL(cen, off) < 0) { + zerror("Invalid zip64 extra block LOC OFFSET value"); + } + // Note: We do not need to adjust the following fields as + // this is the last field we are leveraging + // off += Long.BYTES; + // blockSize -= Long.BYTES; + } else { + zerror("Invalid Zip64 extra block, missing LOC offset value"); + } + } + } + + /** + * Validate the size and contents of a Zip64 extended information field + * The order of the Zip64 fields is fixed, but the fields MUST + * only appear if the corresponding LOC or CEN field is set to 0xFFFF: + * or 0xFFFFFFFF: + * Uncompressed Size - 8 bytes + * Compressed Size - 8 bytes + * LOC Header offset - 8 bytes + * Disk Start Number - 4 bytes + * See PKWare APP.Note Section 4.5.3 for more details + * + * @param blockSize the Zip64 Extended Information Extra Field size + * @param csize CEN header compressed size value + * @param size CEN header uncompressed size value + * @param locoff CEN header LOC offset + * @param diskNo CEN header Disk Number + * @return true if the extra block size is valid; false otherwise + */ + private static boolean isZip64ExtBlockSizeValid(int blockSize, long csize, + long size, long locoff, + int diskNo) { + int expectedBlockSize = + (csize == ZIP64_MINVAL ? Long.BYTES : 0) + + (size == ZIP64_MINVAL ? Long.BYTES : 0) + + (locoff == ZIP64_MINVAL ? Long.BYTES : 0) + + (diskNo == ZIP64_MINVAL32 ? Integer.BYTES : 0); + return expectedBlockSize == blockSize; + } + private final void checkUTF8(byte[] a) throws ZipException { try { int end = a.length; @@ -1632,6 +1802,10 @@ private final void checkUTF8(byte[] a) throws ZipException { } } + private static void zerror(String msg) throws ZipException { + throw new ZipException(msg); + } + private final void checkEncoding( byte[] a) throws ZipException { try { zc.toString(a); @@ -1640,7 +1814,6 @@ private final void checkEncoding( byte[] a) throws ZipException { } } - private void ensureOpen() { if (!isOpen) throw new ClosedFileSystemException(); @@ -2820,9 +2993,9 @@ private void readCEN(ZipFileSystem zipfs, IndexNode inode) throws IOException { int nlen = CENNAM(cen, pos); int elen = CENEXT(cen, pos); int clen = CENCOM(cen, pos); + int diskNo = CENDSK(cen, pos); /* versionMade = CENVEM(cen, pos); - disk = CENDSK(cen, pos); attrs = CENATT(cen, pos); attrsEx = CENATX(cen, pos); */ @@ -2840,6 +3013,9 @@ private void readCEN(ZipFileSystem zipfs, IndexNode inode) throws IOException { extra = Arrays.copyOfRange(cen, pos, pos + elen); pos += elen; readExtra(zipfs); + } else if (elen == 0 && (size == ZIP64_MINVAL || csize == ZIP64_MINVAL + || locoff == ZIP64_MINVAL || diskNo == ZIP64_MINVAL32)) { + throw new ZipException("Invalid CEN header (invalid zip64 extra len size)"); } if (clen > 0) { comment = Arrays.copyOfRange(cen, pos, pos + clen); @@ -3089,7 +3265,7 @@ private void readExtra(ZipFileSystem zipfs) throws IOException { int off = 0; int newOff = 0; boolean hasZip64LocOffset = false; - while (off + 4 < elen) { + while (off + 4 <= elen) { // extra spec: HeaderID+DataSize+Data int pos = off; int tag = SH(extra, pos); @@ -3102,20 +3278,7 @@ private void readExtra(ZipFileSystem zipfs) throws IOException { tag, sz)); } switch (tag) { - case EXTID_ZIP64 : - // if ZIP64_EXTID blocksize == 0, which may occur with some older - // versions of Apache Ant and Commons Compress, validate csize - // size, and locoff to make sure the fields != ZIP64_MAGICVAL - if (sz == 0) { - if (csize == ZIP64_MINVAL || size == ZIP64_MINVAL || locoff == ZIP64_MINVAL) { - throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)"); - } - break; - } - // Check to see if we have a valid block size - if (!isZip64ExtBlockSizeValid(sz)) { - throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)"); - } + case EXTID_ZIP64: if (size == ZIP64_MINVAL) { if (pos + 8 > elen) // invalid zip64 extra break; // fields, just skip @@ -3169,8 +3332,8 @@ private void readExtra(ZipFileSystem zipfs) throws IOException { break; } // If the LOC offset is 0xFFFFFFFF, then we need to read the - // LOC offset from the EXTID_ZIP64 extra data. Therefore - // wait until all of the CEN extra data fields have been processed + // LOC offset from the EXTID_ZIP64 extra data. Therefore, + // wait until all the CEN extra data fields have been processed // prior to reading the LOC extra data field in order to obtain // the Info-ZIP Extended Timestamp. if (locoff != ZIP64_MINVAL) { @@ -3198,36 +3361,6 @@ private void readExtra(ZipFileSystem zipfs) throws IOException { extra = null; } - /** - * Validate the size and contents of a Zip64 extended information field - * The order of the Zip64 fields is fixed, but the fields MUST - * only appear if the corresponding LOC or CEN field is set to 0xFFFF: - * or 0xFFFFFFFF: - * Uncompressed Size - 8 bytes - * Compressed Size - 8 bytes - * LOC Header offset - 8 bytes - * Disk Start Number - 4 bytes - * See PKWare APP.Note Section 4.5.3 for more details - * - * @param blockSize the Zip64 Extended Information Extra Field size - * @return true if the extra block size is valid; false otherwise - */ - private static boolean isZip64ExtBlockSizeValid(int blockSize) { - /* - * As the fields must appear in order, the block size indicates which - * fields to expect: - * 8 - uncompressed size - * 16 - uncompressed size, compressed size - * 24 - uncompressed size, compressed sise, LOC Header offset - * 28 - uncompressed size, compressed sise, LOC Header offset, - * and Disk start number - */ - return switch(blockSize) { - case 8, 16, 24, 28 -> true; - default -> false; - }; - } - /** * Read the LOC extra field to obtain the Info-ZIP Extended Timestamp fields * @param zipfs The Zip FS to use diff --git a/test/jdk/java/util/zip/ZipFile/MissingZIP64EntriesTest.java b/test/jdk/java/util/zip/ZipFile/MissingZIP64EntriesTest.java new file mode 100644 index 00000000000..51a6d0b58ee --- /dev/null +++ b/test/jdk/java/util/zip/ZipFile/MissingZIP64EntriesTest.java @@ -0,0 +1,816 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HexFormat; +import java.util.Map; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; + +import static org.junit.jupiter.api.Assertions.*; + +/* @test + * @bug 8314891 + * @summary Validate that a ZipException is thrown when the extra len is 0 + * and the CEN size, csize,LOC offset fields are set to 0xFFFFFFFF, the disk + * starting number is set to 0xFFFF or when we have a valid Zip64 Extra header + * size but missing the expected header fields. + * @run junit MissingZIP64EntriesTest + */ +public class MissingZIP64EntriesTest { + + /* + * Byte array representing a ZIP file which contains a + * Zip64 Extra Header with only the size field. + * ----------------#1-------------------- + * [Central Directory Header] + * 0x4d: Signature : 0x02014b50 + * 0x51: Created Zip Spec : 0x2d [4.5] + * 0x52: Created OS : 0x0 [MS-DOS] + * 0x53: VerMadeby : 0x2d [0, 4.5] + * 0x54: VerExtract : 0x2d [4.5] + * 0x55: Flag : 0x808 + * 0x57: Method : 0x8 [DEFLATED] + * 0x59: Last Mod Time : 0x57116922 [Thu Aug 17 13:09:04 EDT 2023] + * 0x5d: CRC : 0x57de98d2 + * 0x61: Compressed Size : 0x16 + * 0x65: Uncompressed Size: 0xffffffff + * 0x69: Name Length : 0x9 + * 0x6b: Extra Length : 0xc + * Extra data:[01, 00, 08, 00, 14, 00, 00, 00, 00, 00, 00, 00] + * [tag=0x0001, sz=8] + * ->ZIP64: size *0x14 + * [data= 14 00 00 00 00 00 00 00 ] + * 0x6d: Comment Length : 0x0 + * 0x6f: Disk Start : 0x0 + * 0x71: Attrs : 0x0 + * 0x73: AttrsEx : 0x0 + * 0x77: Loc Header Offset: 0x0 + * 0x7b: File Name : Hello.txt + */ + public static byte[] ZIP_WITH_ZIP64_EXTRAHDR_SIZE_ONLY_BYTEARRAY = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x22, (byte) 0x69, (byte) 0x11, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0xf3, + (byte) 0x48, (byte) 0xcd, (byte) 0xc9, (byte) 0xc9, (byte) 0x57, (byte) 0x8, (byte) 0x49, (byte) 0xcd, + (byte) 0xcb, (byte) 0xcb, (byte) 0x2c, (byte) 0x56, (byte) 0x8, (byte) 0xc8, (byte) 0x49, (byte) 0xac, + (byte) 0x4c, (byte) 0x2d, (byte) 0x2a, (byte) 0x6, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0xd2, (byte) 0x98, (byte) 0xde, (byte) 0x57, (byte) 0x16, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, + (byte) 0x2, (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0x22, (byte) 0x69, (byte) 0x11, (byte) 0x57, (byte) 0xd2, (byte) 0x98, (byte) 0xde, + (byte) 0x57, (byte) 0x16, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0x9, (byte) 0x0, (byte) 0xc, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, + (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x8, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x43, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Byte array representing a Zip file with no extra header fields + * ----------------#1-------------------- + * [Central Directory Header] + * 0x2f: Signature : 0x02014b50 + * 0x33: Created Zip Spec : 0x14 [2.0] + * 0x34: Created OS : 0x3 [UNIX] + * 0x35: VerMadeby : 0x314 [3, 2.0] + * 0x36: VerExtract : 0x14 [2.0] + * 0x37: Flag : 0x2 + * 0x39: Method : 0x8 [DEFLATED] + * 0x3b: Last Mod Time : 0x57039c0d [Thu Aug 03 19:32:26 EDT 2023] + * 0x3f: CRC : 0x31963516 + * 0x43: Compressed Size : 0x8 + * 0x47: Uncompressed Size: 0x6 + * 0x4b: Name Length : 0x9 + * 0x4d: Extra Length : 0x0 + * 0x4f: Comment Length : 0x0 + * 0x51: Disk Start : 0x0 + * 0x53: Attrs : 0x1 + * 0x55: AttrsEx : 0x81a40000 + * 0x59: Loc Header Offset: 0x0 + * 0x5d: File Name : Hello.txt + */ + public static byte[] ZIP_WITH_NO_EXTRA_LEN_BYTEARRAY = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x2, (byte) 0x0, + (byte) 0x8, (byte) 0x0, (byte) 0xd, (byte) 0x9c, (byte) 0x3, (byte) 0x57, (byte) 0x16, (byte) 0x35, + (byte) 0x96, (byte) 0x31, (byte) 0x8, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x6, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0xf3, + (byte) 0x48, (byte) 0xcd, (byte) 0xc9, (byte) 0xc9, (byte) 0xe7, (byte) 0x2, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x14, (byte) 0x3, (byte) 0x14, (byte) 0x0, (byte) 0x2, + (byte) 0x0, (byte) 0x8, (byte) 0x0, (byte) 0xd, (byte) 0x9c, (byte) 0x3, (byte) 0x57, (byte) 0x16, + (byte) 0x35, (byte) 0x96, (byte) 0x31, (byte) 0x8, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x6, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xa4, + (byte) 0x81, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, (byte) 0x6c, + (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x50, (byte) 0x4b, + (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x37, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2f, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Byte array representing a ZIP file which contains a + * Zip64 Extra Header with only the LOC offset field. + * ----------------#1-------------------- + * [Central Directory Header] + * 0x4d: Signature : 0x02014b50 + * 0x51: Created Zip Spec : 0x2d [4.5] + * 0x52: Created OS : 0x0 [MS-DOS] + * 0x53: VerMadeby : 0x2d [0, 4.5] + * 0x54: VerExtract : 0x2d [4.5] + * 0x55: Flag : 0x808 + * 0x57: Method : 0x8 [DEFLATED] + * 0x59: Last Mod Time : 0x572d69c5 [Wed Sep 13 13:14:10 EDT 2023] + * 0x5d: CRC : 0x57de98d2 + * 0x61: Compressed Size : 0x16 + * 0x65: Uncompressed Size: 0x14 + * 0x69: Name Length : 0x9 + * 0x6b: Extra Length : 0xc + * Extra data:[01, 00, 08, 00, 00, 00, 00, 00, 00, 00, 00, 00] + * [tag=0x0001, sz=8] + * ->ZIP64: LOC Off *0x0 + * [data= 00 00 00 00 00 00 00 00 ] + * 0x6d: Comment Length : 0x0 + * 0x6f: Disk Start : 0x0 + * 0x71: Attrs : 0x0 + * 0x73: AttrsEx : 0x0 + * 0x77: Loc Header Offset: 0xffffffff + * 0x7b: File Name : Hello.txt + */ + public static byte[] ZIP_WITH_ZIP64_EXTRAHDR_LOC_ONLY_BYTEARRAY = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0xc5, (byte) 0x69, (byte) 0x2d, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0xf3, + (byte) 0x48, (byte) 0xcd, (byte) 0xc9, (byte) 0xc9, (byte) 0x57, (byte) 0x8, (byte) 0x49, (byte) 0xcd, + (byte) 0xcb, (byte) 0xcb, (byte) 0x2c, (byte) 0x56, (byte) 0x8, (byte) 0xc8, (byte) 0x49, (byte) 0xac, + (byte) 0x4c, (byte) 0x2d, (byte) 0x2a, (byte) 0x6, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0xd2, (byte) 0x98, (byte) 0xde, (byte) 0x57, (byte) 0x16, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, + (byte) 0x2, (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0xc5, (byte) 0x69, (byte) 0x2d, (byte) 0x57, (byte) 0xd2, (byte) 0x98, (byte) 0xde, + (byte) 0x57, (byte) 0x16, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0xc, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, + (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x8, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x43, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Byte array representing a ZIP file which contains a + * Zip64 Extra Header with only the compressed size field. + * ----------------#1-------------------- + * [Central Directory Header] + * 0x4d: Signature : 0x02014b50 + * 0x51: Created Zip Spec : 0x2d [4.5] + * 0x52: Created OS : 0x0 [MS-DOS] + * 0x53: VerMadeby : 0x2d [0, 4.5] + * 0x54: VerExtract : 0x2d [4.5] + * 0x55: Flag : 0x808 + * 0x57: Method : 0x8 [DEFLATED] + * 0x59: Last Mod Time : 0x572d6960 [Wed Sep 13 13:11:00 EDT 2023] + * 0x5d: CRC : 0x57de98d2 + * 0x61: Compressed Size : 0xffffffff + * 0x65: Uncompressed Size: 0x14 + * 0x69: Name Length : 0x9 + * 0x6b: Extra Length : 0xc + * Extra data:[01, 00, 08, 00, 16, 00, 00, 00, 00, 00, 00, 00] + * [tag=0x0001, sz=8] + * ->ZIP64: csize *0x16 + * [data= 16 00 00 00 00 00 00 00 ] + * 0x6d: Comment Length : 0x0 + * 0x6f: Disk Start : 0x0 + * 0x71: Attrs : 0x0 + * 0x73: AttrsEx : 0x0 + * 0x77: Loc Header Offset: 0x0 + * 0x7b: File Name : Hello.txt + */ + public static byte[] ZIP_WITH_ZIP64_EXTRAHDR_CSIZE_ONLY_BYTEARRAY = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x60, (byte) 0x69, (byte) 0x2d, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0xf3, + (byte) 0x48, (byte) 0xcd, (byte) 0xc9, (byte) 0xc9, (byte) 0x57, (byte) 0x8, (byte) 0x49, (byte) 0xcd, + (byte) 0xcb, (byte) 0xcb, (byte) 0x2c, (byte) 0x56, (byte) 0x8, (byte) 0xc8, (byte) 0x49, (byte) 0xac, + (byte) 0x4c, (byte) 0x2d, (byte) 0x2a, (byte) 0x6, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0xd2, (byte) 0x98, (byte) 0xde, (byte) 0x57, (byte) 0x16, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, + (byte) 0x2, (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0x60, (byte) 0x69, (byte) 0x2d, (byte) 0x57, (byte) 0xd2, (byte) 0x98, (byte) 0xde, + (byte) 0x57, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x14, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0xc, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, + (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x8, (byte) 0x0, + (byte) 0x16, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x43, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Byte array representing a Zip file with a zero length ZIP64 Extra Header + * ----------------#1-------------------- + * [Central Directory Header] + * 0x43: Signature : 0x02014b50 + * 0x47: Created Zip Spec : 0x2d [4.5] + * 0x48: Created OS : 0x3 [UNIX] + * 0x49: VerMadeby : 0x32d [3, 4.5] + * 0x4a: VerExtract : 0x2d [4.5] + * 0x4b: Flag : 0x800 + * 0x4d: Method : 0x8 [DEFLATED] + * 0x4f: Last Mod Time : 0x572c3477 [Tue Sep 12 06:35:46 EDT 2023] + * 0x53: CRC : 0x31963516 + * 0x57: Compressed Size : 0x8 + * 0x5b: Uncompressed Size: 0x6 + * 0x5f: Name Length : 0x9 + * 0x61: Extra Length : 0x4 + * Extra data:[01, 00, 00, 00] + * [tag=0x0001, sz=0] + * ->ZIP64: + * 0x63: Comment Length : 0x0 + * 0x65: Disk Start : 0x0 + * 0x67: Attrs : 0x0 + * 0x69: AttrsEx : 0x81a40000 + * 0x6d: Loc Header Offset: 0x0 + * 0x71: File Name : Hello.txt + */ + public static byte[] ZIP_WITH_ZEROLEN_ZIP64_EXTRAHDR_BYTEARRAY = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x77, (byte) 0x34, (byte) 0x2c, (byte) 0x57, (byte) 0x16, (byte) 0x35, + (byte) 0x96, (byte) 0x31, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x9, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x1, + (byte) 0x0, (byte) 0x10, (byte) 0x0, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xf3, (byte) 0x48, (byte) 0xcd, (byte) 0xc9, (byte) 0xc9, + (byte) 0xe7, (byte) 0x2, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x2d, + (byte) 0x3, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x77, + (byte) 0x34, (byte) 0x2c, (byte) 0x57, (byte) 0x16, (byte) 0x35, (byte) 0x96, (byte) 0x31, (byte) 0x8, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x9, + (byte) 0x0, (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xa4, (byte) 0x81, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, + (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, + (byte) 0x6, (byte) 0x6, (byte) 0x2c, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3b, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x43, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, + (byte) 0x6, (byte) 0x7, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x7e, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x3b, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x43, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Byte array representing a ZIP file which contains a + * Zip64 Extra Header with the size and csize fields. + * ----------------#1-------------------- + * [Central Directory Header] + * 0x4d: Signature : 0x02014b50 + * 0x51: Created Zip Spec : 0x2d [4.5] + * 0x52: Created OS : 0x0 [MS-DOS] + * 0x53: VerMadeby : 0x2d [0, 4.5] + * 0x54: VerExtract : 0x2d [4.5] + * 0x55: Flag : 0x808 + * 0x57: Method : 0x8 [DEFLATED] + * 0x59: Last Mod Time : 0x572c6445 [Tue Sep 12 12:34:10 EDT 2023] + * 0x5d: CRC : 0x57de98d2 + * 0x61: Compressed Size : 0xffffffff + * 0x65: Uncompressed Size: 0xffffffff + * 0x69: Name Length : 0x9 + * 0x6b: Extra Length : 0x14 + * Extra data:[01, 00, 10, 00, 14, 00, 00, 00, 00, 00, 00, 00, 16, 00, 00, 00, 00, 00, 00, 00] + * [tag=0x0001, sz=16] + * ->ZIP64: size *0x14 csize *0x16 + * [data= 14 00 00 00 00 00 00 00 16 00 00 00 00 00 00 00 ] + * 0x6d: Comment Length : 0x0 + * 0x6f: Disk Start : 0x0 + * 0x71: Attrs : 0x0 + * 0x73: AttrsEx : 0x0 + * 0x77: Loc Header Offset: 0x0 + * 0x7b: File Name : Hello.txt + */ + public static byte[] ZIP_WITH_TWO_ZIP64_HEADER_ENTRIES_BYTEARRAY = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x45, (byte) 0x64, (byte) 0x2c, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0xf3, + (byte) 0x48, (byte) 0xcd, (byte) 0xc9, (byte) 0xc9, (byte) 0x57, (byte) 0x8, (byte) 0x49, (byte) 0xcd, + (byte) 0xcb, (byte) 0xcb, (byte) 0x2c, (byte) 0x56, (byte) 0x8, (byte) 0xc8, (byte) 0x49, (byte) 0xac, + (byte) 0x4c, (byte) 0x2d, (byte) 0x2a, (byte) 0x6, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0xd2, (byte) 0x98, (byte) 0xde, (byte) 0x57, (byte) 0x16, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, + (byte) 0x2, (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0x45, (byte) 0x64, (byte) 0x2c, (byte) 0x57, (byte) 0xd2, (byte) 0x98, (byte) 0xde, + (byte) 0x57, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0x9, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, + (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x10, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x16, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x4b, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Byte array representing a ZIP file which contains a + * Zip64 Extra Header with the size,csize, and LOC offset fields. + * ----------------#1-------------------- + * [Central Directory Header] + * 0x4d: Signature : 0x02014b50 + * 0x51: Created Zip Spec : 0x2d [4.5] + * 0x52: Created OS : 0x0 [MS-DOS] + * 0x53: VerMadeby : 0x2d [0, 4.5] + * 0x54: VerExtract : 0x2d [4.5] + * 0x55: Flag : 0x808 + * 0x57: Method : 0x8 [DEFLATED] + * 0x59: Last Mod Time : 0x572d7214 [Wed Sep 13 14:16:40 EDT 2023] + * 0x5d: CRC : 0x57de98d2 + * 0x61: Compressed Size : 0xffffffff + * 0x65: Uncompressed Size: 0xffffffff + * 0x69: Name Length : 0x9 + * 0x6b: Extra Length : 0x1c + * Extra data:[01, 00, 18, 00, 14, 00, 00, 00, 00, 00, 00, 00, 16, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + * [tag=0x0001, sz=24] + * ->ZIP64: size *0x14 csize *0x16 LOC Off *0x0 + * [data= 14 00 00 00 00 00 00 00 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ] + * 0x6d: Comment Length : 0x0 + * 0x6f: Disk Start : 0x0 + * 0x71: Attrs : 0x0 + * 0x73: AttrsEx : 0x0 + * 0x77: Loc Header Offset: 0xffffffff + * 0x7b: File Name : Hello.txt + */ + public static byte[] ZIP_WITH_ZIP64_EXTRAHDR_ALL_BYTEARRAY = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x14, (byte) 0x72, (byte) 0x2d, (byte) 0x57, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0xf3, + (byte) 0x48, (byte) 0xcd, (byte) 0xc9, (byte) 0xc9, (byte) 0x57, (byte) 0x8, (byte) 0x49, (byte) 0xcd, + (byte) 0xcb, (byte) 0xcb, (byte) 0x2c, (byte) 0x56, (byte) 0x8, (byte) 0xc8, (byte) 0x49, (byte) 0xac, + (byte) 0x4c, (byte) 0x2d, (byte) 0x2a, (byte) 0x6, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0xd2, (byte) 0x98, (byte) 0xde, (byte) 0x57, (byte) 0x16, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, + (byte) 0x2, (byte) 0x2d, (byte) 0x0, (byte) 0x2d, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0x14, (byte) 0x72, (byte) 0x2d, (byte) 0x57, (byte) 0xd2, (byte) 0x98, (byte) 0xde, + (byte) 0x57, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0x9, (byte) 0x0, (byte) 0x1c, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, + (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, (byte) 0x1, (byte) 0x0, (byte) 0x18, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x16, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x1, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x53, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Enable debug output + */ + private static final boolean DEBUG = false; + + /** + * Name of the Zip file that we create from the byte array + */ + public static final String ZIPFILE_NAME = "validZipFile.zip"; + + /** + * Name of the Zip file that we modify/corrupt + */ + public static final String BAD_ZIP_NAME = "zipWithInvalidZip64ExtraField.zip"; + + /** + * Zip file entry that will be accessed by some the tests + */ + private static final String ZIP_FILE_ENTRY_NAME = "Hello.txt"; + + /** + * Expected Error messages + */ + private static final String INVALID_EXTRA_LENGTH = + "Invalid CEN header (invalid zip64 extra len size)"; + + private static final String INVALID_ZIP64_EXTRAHDR_SIZE = + "Invalid CEN header (invalid zip64 extra data field size)"; + + /** + * Disk starting number offset for the Zip file created from the + * ZIP_WITH_NO_EXTRA_LEN_BYTEARRAY array + */ + private static final int DISKNO_OFFSET_ZIP_NO_EXTRA_LEN = 0x51; + + /** + * Value to set the size, csize, or LOC offset CEN fields to when their + * actual value is stored in the Zip64 Extra Header + */ + private static final long ZIP64_MAGICVAL = 0xFFFFFFFFL; + + /** + * Value to set the Disk Start number offset CEN field to when the + * actual value is stored in the Zip64 Extra Header + */ + private static final int ZIP64_MAGICCOUNT = 0xFFFF; + + /** + * Copy of the byte array for the ZIP to be modified by a given test run + */ + private byte[] zipArrayCopy; + + /** + * Little-endian ByteBuffer for manipulating the ZIP copy + */ + private ByteBuffer buffer; + + /** + * The DataProvider returning a byte array representing the Zip file, + * CEN offsets to set to 0xFFFFFFFF and the expected + * ZipException error message when there are missing Zip64 Extra header fields + * @return Arguments used in each test run + */ + private static Stream InvalidZip64MagicValues() { + return Stream.of( + // Byte array representing the Zip file, compressed size offset, + // and expected ZipException Message + Arguments.of(ZIP_WITH_ZIP64_EXTRAHDR_SIZE_ONLY_BYTEARRAY, + 0x61, INVALID_ZIP64_EXTRAHDR_SIZE), + // Byte array representing the Zip file, LOC offset and expected ZipException Message + Arguments.of(ZIP_WITH_ZIP64_EXTRAHDR_SIZE_ONLY_BYTEARRAY, + 0x77, INVALID_ZIP64_EXTRAHDR_SIZE), + // Byte array representing the Zip file, LOC offset and expected ZipException Message + Arguments.of(ZIP_WITH_TWO_ZIP64_HEADER_ENTRIES_BYTEARRAY, + 0x77, INVALID_ZIP64_EXTRAHDR_SIZE) + ); + } + + /** + * The DataProvider of CEN offsets to set to 0xFFFFFFFF or 0xFFFF when the Extra Length + * size is 0 for the Zip file created using ZIP_WITH_NO_EXTRA_LEN_BYTEARRAY + * @return Arguments used in each test run + */ + private static Stream MissingZip64ExtraFieldEntries() { + return Stream.of( + // Compressed size offset + Arguments.of(0x43), + // Size offset + Arguments.of(0x47), + // Disk start number offset + Arguments.of(DISKNO_OFFSET_ZIP_NO_EXTRA_LEN), + // LOC offset + Arguments.of(0x59) + ); + } + + /** + * The DataProvider of CEN offsets to set to 0xFFFFFFFF when the ZIP64 extra header + * Length size is 0 for the Zip file created using + * ZIP_WITH_ZEROLEN_ZIP64_EXTRAHDR_BYTEARRAY + * @return Arguments used in each test run + */ + private static Stream zip64ZeroLenHeaderExtraFieldEntries() { + return Stream.of( + // Compressed size offset + Arguments.of(0x57), + // Size offset + Arguments.of(0x5b), + // LOC offset + Arguments.of(0x6d) + ); + } + + /** + * The DataProvider which will return a byte array representing a + * valid Zip file and the expected content for the Zip file entry 'Hello.txt'. + * @return Arguments used in each test run + */ + private static Stream validZipFiles() { + return Stream.of( + // Byte array representing the Zip file, and the expected entry content + Arguments.of(ZIP_WITH_ZIP64_EXTRAHDR_SIZE_ONLY_BYTEARRAY, + "Hello Tennis Players"), + Arguments.of(ZIP_WITH_TWO_ZIP64_HEADER_ENTRIES_BYTEARRAY, + "Hello Tennis Players"), + Arguments.of(ZIP_WITH_ZIP64_EXTRAHDR_LOC_ONLY_BYTEARRAY, + "Hello Tennis Players"), + Arguments.of(ZIP_WITH_ZIP64_EXTRAHDR_CSIZE_ONLY_BYTEARRAY, + "Hello Tennis Players"), + Arguments.of(ZIP_WITH_ZIP64_EXTRAHDR_ALL_BYTEARRAY, + "Hello Tennis Players"), + Arguments.of(ZIP_WITH_NO_EXTRA_LEN_BYTEARRAY, + "Hello\n") + ); + } + + /** + * Initial test setup + * @throws IOException if an error occurs + */ + @BeforeAll + public static void setup() throws IOException { + Files.deleteIfExists(Path.of(ZIPFILE_NAME)); + Files.deleteIfExists(Path.of(BAD_ZIP_NAME)); + } + + /** + * Delete the Zip file that will be modified by each test + * @throws IOException if an error occurs + */ + @BeforeEach + public void beforeEachTestRun() throws IOException { + Files.deleteIfExists(Path.of(ZIPFILE_NAME)); + Files.deleteIfExists(Path.of(BAD_ZIP_NAME)); + } + + /** + * Verify that a ZipException is thrown by ZipFile if the Zip64 header + * does not contain the required field + * @param zipArray Byte array representing the Zip file + * @param offset Offset of the CEN Header field to set to 0xFFFFFFFF + * @param errorMessage Expected ZipException error message + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("InvalidZip64MagicValues") + public void invalidZip64ExtraHeaderZipFileTest(byte[] zipArray, int offset, + String errorMessage) throws IOException { + // Set the CEN csize or LOC offset field to 0xFFFFFFFF. There will not + // be the expected Zip64 Extra Header field resulting in a ZipException + // being thrown + zipArrayCopy = zipArray.clone(); + buffer = ByteBuffer.wrap(zipArrayCopy).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset, (int) ZIP64_MAGICVAL); + Files.write(Path.of(BAD_ZIP_NAME), zipArrayCopy); + + ZipException ex = assertThrows(ZipException.class, () -> { + openWithZipFile(BAD_ZIP_NAME, ZIP_FILE_ENTRY_NAME, null); + }); + assertTrue(ex.getMessage().equals(errorMessage), + "Unexpected ZipException message: " + ex.getMessage()); + } + + /** + * Verify that a ZipException is thrown by Zip FS if the Zip64 header + * does not contain the required field + * @param zipArray Byte array representing the Zip file + * @param offset Offset of the CEN Header field to set to 0xFFFFFFFF + * @param errorMessage Expected ZipException error message + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("InvalidZip64MagicValues") + public void invalidZip64ExtraHeaderZipFSTest(byte[] zipArray, int offset, + String errorMessage) throws IOException { + // Set the CEN csize or LOC offset field to 0xFFFFFFFF. There will not + // be the expected Zip64 Extra Header field resulting in a ZipException + // being thrown + zipArrayCopy = zipArray.clone(); + buffer = ByteBuffer.wrap(zipArrayCopy).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset, (int)ZIP64_MAGICVAL); + Files.write(Path.of(BAD_ZIP_NAME), zipArrayCopy); + + ZipException ex = assertThrows(ZipException.class, () -> { + openWithZipFS(BAD_ZIP_NAME, ZIP_FILE_ENTRY_NAME, null); + }); + assertTrue(ex.getMessage().equals(errorMessage), + "Unexpected ZipException message: " + ex.getMessage()); + } + + /** + * Verify that ZipFile will throw a ZipException if the CEN + * Extra length is 0 and the CEN size, csize, LOC offset field is set to + * 0xFFFFFFFF or the disk starting number is set to 0xFFFF + * @param offset Offset of the CEN Header field to set to 0xFFFFFFFF or 0xFFFF + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("MissingZip64ExtraFieldEntries") + public void zipFileBadExtraLength(int offset) throws IOException { + zipArrayCopy = ZIP_WITH_NO_EXTRA_LEN_BYTEARRAY.clone(); + buffer = ByteBuffer.wrap(zipArrayCopy).order(ByteOrder.LITTLE_ENDIAN); + if (offset == DISKNO_OFFSET_ZIP_NO_EXTRA_LEN) { + buffer.putShort(offset, (short) ZIP64_MAGICCOUNT); + } else { + buffer.putInt(offset, (int) ZIP64_MAGICVAL); + } + Files.write(Path.of(BAD_ZIP_NAME), zipArrayCopy); + + ZipException ex = assertThrows(ZipException.class, () -> { + openWithZipFile(BAD_ZIP_NAME, ZIP_FILE_ENTRY_NAME, null); + }); + assertTrue(ex.getMessage().equals(INVALID_EXTRA_LENGTH), + "Unexpected ZipException message: " + ex.getMessage()); + } + + /** + * Verify that ZipFS will throw a ZipException if the CEN + * Extra length is 0 and the CEN size, csize, LOC offset field is set to + * 0xFFFFFFFF or the disk starting number is set to 0xFFFF + * @param offset the offset of the CEN Header field to set to 0xFFFFFFFF or 0xFFFF + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("MissingZip64ExtraFieldEntries") + public void zipFSBadExtraLength(int offset) throws IOException { + zipArrayCopy = ZIP_WITH_NO_EXTRA_LEN_BYTEARRAY.clone(); + buffer = ByteBuffer.wrap(zipArrayCopy).order(ByteOrder.LITTLE_ENDIAN); + if (offset == DISKNO_OFFSET_ZIP_NO_EXTRA_LEN) { + buffer.putShort(offset, (short) ZIP64_MAGICCOUNT); + } else { + buffer.putInt(offset, (int) ZIP64_MAGICVAL); + } + Files.write(Path.of(BAD_ZIP_NAME), zipArrayCopy); + + ZipException ex = assertThrows(ZipException.class, () -> { + openWithZipFS(BAD_ZIP_NAME, ZIP_FILE_ENTRY_NAME, null); + }); + assertTrue(ex.getMessage().equals(INVALID_EXTRA_LENGTH), + "Unexpected ZipException message: " + ex.getMessage()); + } + + /** + * Verify that ZipFile will throw a ZipException if the ZIP64 extra header + * has a size of 0 and the CEN size, csize, or the LOC offset field is set to + * 0xFFFFFFFF + * @param offset the offset of the CEN Header field to set to 0xFFFFFFFF + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("zip64ZeroLenHeaderExtraFieldEntries") + public void zipFileZeroLenExtraHeader(int offset) throws IOException { + zipArrayCopy = ZIP_WITH_ZEROLEN_ZIP64_EXTRAHDR_BYTEARRAY.clone(); + buffer = ByteBuffer.wrap(zipArrayCopy).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset, (int) ZIP64_MAGICVAL); + Files.write(Path.of(BAD_ZIP_NAME), zipArrayCopy); + ZipException ex = assertThrows(ZipException.class, () -> { + openWithZipFile(BAD_ZIP_NAME, ZIP_FILE_ENTRY_NAME, null); + }); + assertTrue(ex.getMessage().equals(INVALID_ZIP64_EXTRAHDR_SIZE), + "Unexpected ZipException message: " + ex.getMessage()); + } + + /** + * Verify that ZipFS will throw a ZipException if the ZIP64 extra header + * has a size of 0 and the CEN size, csize, or the LOC offset field is set to + * 0xFFFFFFFF + * @param offset the offset of the CEN Header field to set to 0xFFFFFFFF + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("zip64ZeroLenHeaderExtraFieldEntries") + public void zipFSZeroLenExtraHeader(int offset) throws IOException { + zipArrayCopy = ZIP_WITH_ZEROLEN_ZIP64_EXTRAHDR_BYTEARRAY.clone(); + buffer = ByteBuffer.wrap(zipArrayCopy).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(offset, (int) ZIP64_MAGICVAL); + Files.write(Path.of(BAD_ZIP_NAME), zipArrayCopy); + ZipException ex = assertThrows(ZipException.class, () -> { + openWithZipFS(BAD_ZIP_NAME, ZIP_FILE_ENTRY_NAME, null); + }); + assertTrue(ex.getMessage().equals(INVALID_ZIP64_EXTRAHDR_SIZE), + "Unexpected ZipException message: " + ex.getMessage()); + } + + /** + * Verify that ZipFile will read the Zip files created from the + * byte arrays prior to modifying the arrays to check that the + * expected ZipException is thrown. + * @param zipFile the byte array which represents the Zip file that should + * be opened and read successfully. + * @param message the expected text contained within the Zip entry + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("validZipFiles") + public void readValidZipFile(byte[] zipFile, String message) throws IOException { + // Write out the Zip file from the byte array + Files.write(Path.of(ZIPFILE_NAME), zipFile); + openWithZipFile(ZIPFILE_NAME, ZIP_FILE_ENTRY_NAME, message); + } + + /** + * Verify that ZipFS will read the Zip files created from the + * byte arrays prior to modifying the arrays to check that the + * expected ZipException is thrown. + * @param zipFile the byte array which represents the Zip file that should + * be opened and read successfully. + * @param message the expected text contained within the Zip entry + * @throws IOException if an error occurs + */ + @ParameterizedTest + @MethodSource("validZipFiles") + public void readValidZipFileWithZipFs(byte[] zipFile, String message) + throws IOException { + // Write out the Zip file from the byte array + Files.write(Path.of(ZIPFILE_NAME), zipFile); + openWithZipFS(ZIPFILE_NAME, ZIP_FILE_ENTRY_NAME, message); + } + + /** + * Utility method used to open a Zip file using ZipFile by the tests. + * @param zipFile name of the Zip file to open + * @param entryName Zip entry to read when the Zip file is expected to be + * able to be opened + * @param entryContents the expected contents for the Zip entry + * @throws IOException if an error occurs + */ + private static void openWithZipFile(String zipFile, String entryName, + String entryContents) throws IOException { + try (ZipFile zf = new ZipFile(zipFile)) { + ZipEntry ze = zf.getEntry(entryName); + try (InputStream is = zf.getInputStream(ze)) { + String result = new String(is.readAllBytes()); + if (DEBUG) { + var hx = HexFormat.ofDelimiter(", ").withPrefix("0x"); + System.out.printf("Error: Zip File read :%s%n[%s]%n", result, + hx.formatHex(result.getBytes())); + } + // entryContents will be null when an exception is expected + if (entryContents != null) { + assertEquals(entryContents, result); + } + } + } + } + + /** + * Utility method used to open a Zip file using ZipFS by the tests. + * @param zipFile name of the Zip file to open + * @param entryName Zip entry to read when the Zip file is expected to be + * able to be opened + * @param entryContents the expected contents for the Zip entry + * @throws IOException if an error occurs + */ + private static void openWithZipFS(String zipFile, String entryName, + String entryContents) throws IOException { + try (FileSystem fs = FileSystems.newFileSystem( + Path.of(zipFile), Map.of())) { + Path p = fs.getPath(entryName); + String result = new String(Files.readAllBytes(p)); + if (DEBUG) { + var hx = HexFormat.ofDelimiter(", ").withPrefix("0x"); + System.out.printf("Error: Zip FS read :%s%n[%s]%n", result, + hx.formatHex(result.getBytes())); + } + // entryContents will be null when an exception is expected + if (entryContents != null) { + assertEquals(entryContents, result); + } + } + } +} From 632f56c297a11578b8638460f63ba71a1928933a Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 7 Nov 2023 17:00:08 +0000 Subject: [PATCH 26/31] 8319436: Proxy.newProxyInstance throws NPE if loader is null and interface not visible from class loader Reviewed-by: alanb --- .../share/classes/java/lang/System.java | 2 +- .../lang/reflect/Proxy/ClassRestrictions.java | 187 ++++++------------ 2 files changed, 66 insertions(+), 123 deletions(-) diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index e7ed153c620..6c7de7c7798 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -2667,7 +2667,7 @@ public StackWalker newStackWalkerInstance(Set options, } public String getLoaderNameID(ClassLoader loader) { - return loader.nameAndId(); + return loader != null ? loader.nameAndId() : "null"; } @Override diff --git a/test/jdk/java/lang/reflect/Proxy/ClassRestrictions.java b/test/jdk/java/lang/reflect/Proxy/ClassRestrictions.java index ba5b407b99d..6f6dcb4d75b 100644 --- a/test/jdk/java/lang/reflect/Proxy/ClassRestrictions.java +++ b/test/jdk/java/lang/reflect/Proxy/ClassRestrictions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,13 +22,13 @@ */ /* @test - * @bug 4227192 8004928 8072656 + * @bug 4227192 8004928 8072656 8319436 * @summary This is a test of the restrictions on the parameters that may * be passed to the Proxy.getProxyClass method. * @author Peter Jones * * @build ClassRestrictions - * @run main ClassRestrictions + * @run junit ClassRestrictions */ import java.io.File; @@ -37,6 +37,13 @@ import java.net.URLClassLoader; import java.net.URL; import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; public class ClassRestrictions { @@ -52,129 +59,65 @@ interface Bashful { void foo(); } - public static final String nonPublicIntrfaceName = "java.util.zip.ZipConstants"; - - public static void main(String[] args) { - - System.err.println( - "\nTest of restrictions on parameters to Proxy.getProxyClass\n"); - - try { - ClassLoader loader = ClassRestrictions.class.getClassLoader(); - Class[] interfaces; - Class proxyClass; - - /* - * All of the Class objects in the interfaces array must represent - * interfaces, not classes or primitive types. - */ - try { - interfaces = new Class[] { Object.class }; - proxyClass = Proxy.getProxyClass(loader, interfaces); - throw new Error( - "proxy class created with java.lang.Object as interface"); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - System.err.println(); - // assume exception is for intended failure - } - try { - interfaces = new Class[] { Integer.TYPE }; - proxyClass = Proxy.getProxyClass(loader, interfaces); - throw new Error( - "proxy class created with int.class as interface"); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - System.err.println(); - // assume exception is for intended failure - } - - /* - * No two elements in the interfaces array may refer to identical - * Class objects. - */ - try { - interfaces = new Class[] { Bar.class, Bar.class }; - proxyClass = Proxy.getProxyClass(loader, interfaces); - throw new Error( - "proxy class created with repeated interfaces"); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - System.err.println(); - // assume exception is for intended failure - } - - /* - * All of the interfaces types must be visible by name though the - * specified class loader. - */ - String[] cpaths = System.getProperty("test.classes", ".") - .split(File.pathSeparator); - URL[] urls = new URL[cpaths.length]; - for (int i=0; i < cpaths.length; i++) { - urls[i] = Paths.get(cpaths[i]).toUri().toURL(); - } - ClassLoader altLoader = new URLClassLoader(urls, null); - Class altBarClass; - altBarClass = Class.forName(Bar.class.getName(), false, altLoader); - try { - interfaces = new Class[] { altBarClass }; - proxyClass = Proxy.getProxyClass(loader, interfaces); - throw new Error( - "proxy class created with interface " + - "not visible to class loader"); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - System.err.println(); - // assume exception is for intended failure - } + private static final String TEST_CLASSES = System.getProperty("test.classes", "."); + private static final ClassLoader LOADER = ClassRestrictions.class.getClassLoader(); + + static Stream>> badProxyInterfaces() { + return Stream.of( + List.of(Object.class), // proxy interface cannot be a class + List.of(int.class), // proxy interface can't be primitive type + List.of(Bar.class, Bar.class), // cannot have repeated interfaces + // two proxy interfaces have the method of same method name but different return type + List.of(Bar.class, Baz.class) + ); + } - /* - * All non-public interfaces must be in the same package. - */ - Class nonPublic1 = Bashful.class; - Class nonPublic2 = Class.forName(nonPublicIntrfaceName); - if (Modifier.isPublic(nonPublic2.getModifiers())) { - throw new Error( - "Interface " + nonPublicIntrfaceName + - " is public and need to be changed!"); - } - try { - interfaces = new Class[] { nonPublic1, nonPublic2 }; - proxyClass = Proxy.getProxyClass(loader, interfaces); - throw new Error( - "proxy class created with two non-public interfaces " + - "in different packages"); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - System.err.println(); - // assume exception is for intended failure - } + /* + * Test cases for illegal proxy interfaces + */ + @ParameterizedTest + @MethodSource("badProxyInterfaces") + void testForName(List> interfaces) { + assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(LOADER, interfaces.toArray(Class[]::new))); + } - /* - * No two interfaces may each have a method with the same name and - * parameter signature but different return type. - */ - try { - interfaces = new Class[] { Bar.class, Baz.class }; - proxyClass = Proxy.getProxyClass(loader, interfaces); - throw new Error( - "proxy class created with conflicting methods"); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - System.err.println(); - // assume exception is for intended failure - } + private static final String nonPublicIntrfaceName = "java.util.zip.ZipConstants"; + + /* + * All non-public interfaces must be in the same package. + */ + @Test + void testNonPublicIntfs() throws Exception { + var nonPublic1 = Bashful.class; + var nonPublic2 = Class.forName(nonPublicIntrfaceName); + assertFalse(Modifier.isPublic(nonPublic2.getModifiers()), + "Interface " + nonPublicIntrfaceName + " is public and need to be changed!"); + var interfaces = new Class[] { nonPublic1, nonPublic2 }; + assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(LOADER, interfaces)); + } - /* - * All components of this test have passed. - */ - System.err.println("\nTEST PASSED"); + static Stream loaders() { + return Stream.of(null, + ClassLoader.getPlatformClassLoader(), + ClassLoader.getSystemClassLoader(), + LOADER); + } - } catch (Throwable e) { - System.err.println("\nTEST FAILED:"); - e.printStackTrace(); - throw new Error("TEST FAILED: ", e); + /* + * All of the interfaces types must be visible by name though the + * specified class loader. + */ + @ParameterizedTest + @MethodSource("loaders") + void testNonVisibleInterface(ClassLoader loader) throws Exception { + String[] cpaths = TEST_CLASSES.split(File.pathSeparator); + URL[] urls = new URL[cpaths.length]; + for (int i = 0; i < cpaths.length; i++) { + urls[i] = Paths.get(cpaths[i]).toUri().toURL(); } + var altLoader = new URLClassLoader(urls, null); + var altBarClass = Class.forName(Bar.class.getName(), false, altLoader); + var interfaces = new Class[]{ altBarClass }; + assertThrows(IllegalArgumentException.class, () -> Proxy.getProxyClass(loader, interfaces)); } } From e0a4fdef684d3985614ea53f945b642907a22497 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 7 Nov 2023 17:07:43 +0000 Subject: [PATCH 27/31] 8319338: tools/jpackage/share/RuntimeImageTest.java fails with -XX:+UseZGC Reviewed-by: almatvee, alanb --- test/jdk/tools/jpackage/share/RuntimeImageTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/tools/jpackage/share/RuntimeImageTest.java b/test/jdk/tools/jpackage/share/RuntimeImageTest.java index 36009f570c3..44088778589 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageTest.java @@ -38,7 +38,7 @@ * @build jdk.jpackage.test.* * @modules jdk.jpackage/jdk.jpackage.internal * @compile RuntimeImageTest.java - * @run main/othervm/timeout=1400 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=1400 jdk.jpackage.test.Main * --jpt-run=RuntimeImageTest */ From 2f01c1d76519b0174b08d8dd5254f5e4db1b3db3 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Tue, 7 Nov 2023 17:13:47 +0000 Subject: [PATCH 28/31] 8319573: Change to Visual Studio 17.6.5 for building on Windows at Oracle Reviewed-by: erikj --- doc/building.html | 2 +- doc/building.md | 10 +++++----- make/conf/jib-profiles.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/building.html b/doc/building.html index 3601fa8af16..3d6df55fa12 100644 --- a/doc/building.html +++ b/doc/building.html @@ -548,7 +548,7 @@

      Native Compiler

  • - +
    WindowsMicrosoft Visual Studio 2022 update 17.1.0Microsoft Visual Studio 2022 version 17.6.5
    diff --git a/doc/building.md b/doc/building.md index 68c65bf0517..aff2a1abe9c 100644 --- a/doc/building.md +++ b/doc/building.md @@ -334,11 +334,11 @@ possible to compile the JDK with both older and newer versions, but the closer you stay to this list, the more likely you are to compile successfully without issues. -| Operating system | Toolchain version | -| ------------------ | ------------------------------------------ | -| Linux | gcc 11.2.0 | -| macOS | Apple Xcode 14.3.1 (using clang 14.0.3) | -| Windows | Microsoft Visual Studio 2022 update 17.1.0 | +| Operating system | Toolchain version | +| ------------------ | ------------------------------------------- | +| Linux | gcc 11.2.0 | +| macOS | Apple Xcode 14.3.1 (using clang 14.0.3) | +| Windows | Microsoft Visual Studio 2022 version 17.6.5 | All compilers are expected to be able to compile to the C99 language standard, as some C99 features are used in the source code. Microsoft Visual Studio diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index e81b6715a48..e038dbd9006 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1087,7 +1087,7 @@ var getJibProfilesDependencies = function (input, common) { var devkit_platform_revisions = { linux_x64: "gcc11.2.0-OL6.4+1.0", macosx: "Xcode14.3.1+1.0", - windows_x64: "VS2022-17.1.0+1.1", + windows_x64: "VS2022-17.6.5+1.0", linux_aarch64: input.build_cpu == "x64" ? "gcc11.2.0-OL7.6+1.1" : "gcc11.2.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", linux_ppc64le: "gcc8.2.0-Fedora27+1.0", From 39b2c47c249eabdc06a42dd116dff19986da8503 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Tue, 7 Nov 2023 19:21:03 +0000 Subject: [PATCH 29/31] 8305814: Update Xalan Java to 2.7.3 Reviewed-by: iris, lancea, naoto --- .../xalan/internal/lib/ExsltDatetime.java | 55 +++++++++---------- .../xalan/internal/xsltc/compiler/Mode.java | 12 ++-- .../xml/internal/dtm/ref/DTMStringPool.java | 39 +++---------- src/java.xml/share/legal/xalan.md | 2 +- 4 files changed, 41 insertions(+), 67 deletions(-) diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/lib/ExsltDatetime.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/lib/ExsltDatetime.java index f8ce5a924d6..2abd11227f4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/lib/ExsltDatetime.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/lib/ExsltDatetime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,16 +21,20 @@ package com.sun.org.apache.xalan.internal.lib; +import com.sun.org.apache.xpath.internal.objects.XBoolean; +import com.sun.org.apache.xpath.internal.objects.XNumber; +import com.sun.org.apache.xpath.internal.objects.XObject; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; - -import com.sun.org.apache.xpath.internal.objects.XBoolean; -import com.sun.org.apache.xpath.internal.objects.XNumber; -import com.sun.org.apache.xpath.internal.objects.XObject; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; /** * This class contains EXSLT dates and times extension functions. @@ -44,7 +48,7 @@ * * @see EXSLT * @xsl.usage general - * @LastModified: Nov 2017 + * @LastModified: Nov 2023 */ public class ExsltDatetime @@ -75,29 +79,19 @@ public class ExsltDatetime */ public static String dateTime() { - Calendar cal = Calendar.getInstance(); - Date datetime = cal.getTime(); - // Format for date and time. - SimpleDateFormat dateFormat = new SimpleDateFormat(dt); - - StringBuffer buff = new StringBuffer(dateFormat.format(datetime)); - // Must also include offset from UTF. - // Get the offset (in milliseconds). - int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET); - // If there is no offset, we have "Coordinated - // Universal Time." - if (offset == 0) - buff.append("Z"); - else - { - // Convert milliseconds to hours and minutes - int hrs = offset/(60*60*1000); - // In a few cases, the time zone may be +/-hh:30. - int min = offset%(60*60*1000); - char posneg = hrs < 0? '-': '+'; - buff.append(posneg).append(formatDigits(hrs)).append(':').append(formatDigits(min)); + String resultStr = ""; + try { + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(new Date()); + XMLGregorianCalendar xCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal); + xCal.setMillisecond(DatatypeConstants.FIELD_UNDEFINED); + resultStr = xCal.toXMLFormat(); } - return buff.toString(); + catch (DatatypeConfigurationException ex) { + + } + + return resultStr; } /** @@ -135,6 +129,7 @@ private static String formatDigits(int q) public static String date(String datetimeIn) throws ParseException { + if ("".equals(datetimeIn)) return EMPTY_STR; String[] edz = getEraDatetimeZone(datetimeIn); String leader = edz[0]; String datetime = edz[1]; @@ -251,7 +246,7 @@ public static double year(String datetimeIn) String[] formats = {dt, d, gym, gy}; double yr = getNumber(datetime, formats, Calendar.YEAR); - if (ad || yr == Double.NaN) + if (ad || Double.isNaN(yr)) return yr; else return -yr; @@ -604,7 +599,7 @@ public static XObject leapYear(String datetimeIn) String[] formats = {dt, d, gym, gy}; double dbl = getNumber(datetime, formats, Calendar.YEAR); - if (dbl == Double.NaN) + if (Double.isNaN(dbl)) return new XNumber(Double.NaN); int yr = (int)dbl; return new XBoolean(yr % 400 == 0 || (yr % 100 != 0 && yr % 4 == 0)); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Mode.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Mode.java index 2c1f7e64551..3da8ce778a3 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Mode.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Mode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -63,7 +63,7 @@ * @author Morten Jorgensen * @author Erwin Bolwidt * @author G. Todd Miller - * @LastModified: Sep 2021 + * @LastModified: Nov 2023 */ final class Mode implements Constants { @@ -841,7 +841,7 @@ argTypes, argNames, functionName(), elemPrio = elemTest.getPriority(); elemPos = elemTest.getPosition(); } - if (elemPrio == Double.NaN || elemPrio < nodePrio || + if (Double.isNaN(elemPrio) || elemPrio < nodePrio || (elemPrio == nodePrio && elemPos < nodePos)) { ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); @@ -856,7 +856,7 @@ argTypes, argNames, functionName(), textPrio = textTest.getPriority(); textPos = textTest.getPosition(); } - if (textPrio == Double.NaN || textPrio < nodePrio || + if (Double.isNaN(textPrio) || textPrio < nodePrio || (textPrio == nodePrio && textPos < nodePos)) { ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); @@ -1181,7 +1181,7 @@ argTypes, argNames, functionName()+'_'+max, elemPos = elemTest.getPosition(); } - if (elemPrio == Double.NaN || elemPrio < nodePrio || + if (Double.isNaN(elemPrio) || elemPrio < nodePrio || (elemPrio == nodePrio && elemPos < nodePos)) { ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); @@ -1197,7 +1197,7 @@ argTypes, argNames, functionName()+'_'+max, textPos = textTest.getPosition(); } - if (textPrio == Double.NaN || textPrio < nodePrio || + if (Double.isNaN(textPrio) || textPrio < nodePrio || (textPrio == nodePrio && textPos < nodePos)) { ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMStringPool.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMStringPool.java index a83ee2ac88e..d8ee1d69904 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMStringPool.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/DTMStringPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -20,8 +20,8 @@ package com.sun.org.apache.xml.internal.dtm.ref; -import com.sun.org.apache.xml.internal.utils.IntVector; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; /**

    DTMStringPool is an "interning" mechanism for strings. It will @@ -53,14 +53,12 @@ * *

    Status: Passed basic test in main().

    * - * @LastModified: Oct 2017 + * @LastModified: Nov 2023 */ public class DTMStringPool { List m_intToString; - static final int HASHPRIME=101; - int[] m_hashStart=new int[HASHPRIME]; - IntVector m_hashChain; + HashMap m_stringToInt; public static final int NULL=-1; /** @@ -71,7 +69,7 @@ public class DTMStringPool public DTMStringPool(int chainSize) { m_intToString = new ArrayList<>(); - m_hashChain= new IntVector(chainSize); + m_stringToInt = new HashMap<>(); removeAllElements(); // -sb Add this to force empty strings to be index 0. @@ -86,9 +84,7 @@ public DTMStringPool() public void removeAllElements() { m_intToString.clear(); - for(int i=0;i From 2bc666ba69c2a1724173f0db8023e5435030adbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C3=B6=20Barany?= Date: Tue, 7 Nov 2023 19:23:53 +0000 Subject: [PATCH 30/31] 8315680: java/lang/ref/ReachabilityFenceTest.java should run with -Xbatch Reviewed-by: dnsimon, never, psandoz --- test/jdk/java/lang/ref/ReachabilityFenceTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/jdk/java/lang/ref/ReachabilityFenceTest.java b/test/jdk/java/lang/ref/ReachabilityFenceTest.java index 4ddc9e0c9eb..9dde3f6b81d 100644 --- a/test/jdk/java/lang/ref/ReachabilityFenceTest.java +++ b/test/jdk/java/lang/ref/ReachabilityFenceTest.java @@ -27,11 +27,11 @@ * * @requires vm.opt.DeoptimizeALot != true * - * @run main/othervm -Xint -Dpremature=false ReachabilityFenceTest - * @run main/othervm -XX:TieredStopAtLevel=1 -Dpremature=true ReachabilityFenceTest - * @run main/othervm -XX:TieredStopAtLevel=2 -Dpremature=true ReachabilityFenceTest - * @run main/othervm -XX:TieredStopAtLevel=3 -Dpremature=true ReachabilityFenceTest - * @run main/othervm -XX:TieredStopAtLevel=4 -Dpremature=true ReachabilityFenceTest + * @run main/othervm -Xint -Dpremature=false ReachabilityFenceTest + * @run main/othervm -Xbatch -XX:TieredStopAtLevel=1 -Dpremature=true ReachabilityFenceTest + * @run main/othervm -Xbatch -XX:TieredStopAtLevel=2 -Dpremature=true ReachabilityFenceTest + * @run main/othervm -Xbatch -XX:TieredStopAtLevel=3 -Dpremature=true ReachabilityFenceTest + * @run main/othervm -Xbatch -XX:TieredStopAtLevel=4 -Dpremature=true ReachabilityFenceTest */ import java.lang.ref.Reference; @@ -54,7 +54,7 @@ public class ReachabilityFenceTest { * the object cannot be finalized. There is no sense running a positive test when premature finalization * is not expected. It is a job for negative test to verify that invariant. * - * The test methods should be appropriately compiled, therefore we do several iterations. + * The test methods should be appropriately compiled, therefore we do several iterations and run with -Xbatch. */ // Enough to OSR and compile From a1a092064d40aad12bf640dea74f1494d78f109b Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Tue, 7 Nov 2023 21:33:33 +0000 Subject: [PATCH 31/31] 8319378: Spec for j.util.Timer::purge and j.util.Timer::cancel could be improved Reviewed-by: naoto, jpai, rriggs --- .../share/classes/java/util/Timer.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/java.base/share/classes/java/util/Timer.java b/src/java.base/share/classes/java/util/Timer.java index 6221667d69c..1029a715953 100644 --- a/src/java.base/share/classes/java/util/Timer.java +++ b/src/java.base/share/classes/java/util/Timer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ *

    This class does not offer real-time guarantees: it schedules * tasks using the {@code Object.wait(long)} method. * - *

    Java 5.0 introduced the {@code java.util.concurrent} package and + * @apiNote Java 5.0 introduced the {@code java.util.concurrent} package and * one of the concurrency utilities therein is the {@link * java.util.concurrent.ScheduledThreadPoolExecutor * ScheduledThreadPoolExecutor} which is a thread pool for repeatedly @@ -74,13 +74,11 @@ * implement {@code Runnable}). Configuring {@code * ScheduledThreadPoolExecutor} with one thread makes it equivalent to * {@code Timer}. - * - *

    Implementation note: This class scales to large numbers of concurrently + * @implNote This class scales to large numbers of concurrently * scheduled tasks (thousands should present no problem). Internally, * it uses a binary heap to represent its task queue, so the cost to schedule * a task is O(log n), where n is the number of concurrently scheduled tasks. - * - *

    Implementation note: All constructors start a timer thread. + *

    All constructors start a timer thread. * * @author Josh Bloch * @see TimerTask @@ -424,8 +422,12 @@ private void sched(TimerTask task, long time, long period) { } /** - * Terminates this timer, discarding any currently scheduled tasks. - * Does not interfere with a currently executing task (if it exists). + * Terminates this timer, discarding any currently scheduled tasks. + * It should be noted that this method does not cancel the scheduled + * tasks. For a task to be considered cancelled, the task itself should + * invoke {@link TimerTask#cancel()}. + * + *

    This method does not interfere with a currently executing task (if it exists). * Once a timer has been terminated, its execution thread terminates * gracefully, and no more tasks may be scheduled on it. * @@ -436,6 +438,7 @@ private void sched(TimerTask task, long time, long period) { * *

    This method may be called repeatedly; the second and subsequent * calls have no effect. + * @see TimerTask#cancel() */ public void cancel() { synchronized(queue) { @@ -445,23 +448,25 @@ public void cancel() { } /** - * Removes all cancelled tasks from this timer's task queue. Calling - * this method has no effect on the behavior of the timer, but - * eliminates the references to the cancelled tasks from the queue. + * Removes all cancelled tasks from this timer's task queue. + * Calling this method has no effect on the behavior of the timer, + * but eliminates the references to the cancelled tasks from the queue. * If there are no external references to these tasks, they become * eligible for garbage collection. * *

    Most programs will have no need to call this method. * It is designed for use by the rare application that cancels a large * number of tasks. Calling this method trades time for space: the - * runtime of the method may be proportional to n + c log n, where n - * is the number of tasks in the queue and c is the number of cancelled - * tasks. + * runtime of the method may be proportional to {@code n + c log n}, where + * {@code n} is the number of tasks in the queue and {@code c} is the number + * of cancelled tasks. * *

    Note that it is permissible to call this method from within * a task scheduled on this timer. * * @return the number of tasks removed from the queue. + * @see #cancel() + * @see TimerTask#cancel() * @since 1.5 */ public int purge() {