From b659d744231d1d852d2ff3935685e0ea2300cbcd Mon Sep 17 00:00:00 2001
From: Lana Steuck ";
- os.write (s.getBytes());
+ fis.close();
os.close();
- t.close();
}
}
-class EchoHandler implements HttpHandler {
-
- byte[] read(InputStream is) throws IOException {
- byte[] buf = new byte[1024];
- byte[] result = new byte[0];
-
- while (true) {
- int n = is.read(buf);
- if (n > 0) {
- byte[] b1 = new byte[result.length + n];
- System.arraycopy(result, 0, b1, 0, result.length);
- System.arraycopy(buf, 0, b1, result.length, n);
- result = b1;
- } else if (n == -1) {
- return result;
- }
- }
+ void moved (HttpExchange t) throws IOException {
+ Headers req = t.getRequestHeaders();
+ Headers map = t.getResponseHeaders();
+ URI uri = t.getRequestURI();
+ String host = req.getFirst ("Host");
+ String location = "http://"+host+uri.getPath() + "/";
+ map.set ("Content-Type", "text/html");
+ map.set ("Location", location);
+ t.sendResponseHeaders (301, -1);
+ t.close();
}
- public void handle (HttpExchange t)
- throws IOException
- {
- InputStream is = t.getRequestBody();
- Headers map = t.getRequestHeaders();
- String fixedrequest = map.getFirst ("XFixed");
-
- // return the number of bytes received (no echo)
- String summary = map.getFirst ("XSummary");
- if (fixedrequest != null && summary == null) {
- byte[] in = read(is);
- t.sendResponseHeaders(200, in.length);
- OutputStream os = t.getResponseBody();
- os.write(in);
- close(os);
- close(is);
- } else {
- OutputStream os = t.getResponseBody();
- byte[] buf = new byte[64 * 1024];
- t.sendResponseHeaders(200, 0);
- int n, count=0;;
-
- while ((n = is.read(buf)) != -1) {
- if (summary == null) {
- os.write(buf, 0, n);
- }
- count += n;
- }
- if (summary != null) {
- String s = Integer.toString(count);
- os.write(s.getBytes());
- }
- close(os);
- close(is);
- }
- }
-
- protected void close(OutputStream os) throws IOException {
- os.close();
- }
- protected void close(InputStream is) throws IOException {
- is.close();
- }
+ void notfound (HttpExchange t, String p) throws IOException {
+ t.getResponseHeaders().set ("Content-Type", "text/html");
+ t.sendResponseHeaders (404, 0);
+ OutputStream os = t.getResponseBody();
+ String s = " ";
+ os.write (s.getBytes());
+ os.close();
+ t.close();
}
+}
diff --git a/jdk/test/com/sun/net/httpserver/SimpleFileServer.java b/jdk/test/com/sun/net/httpserver/SimpleFileServer.java
new file mode 100644
index 00000000000..0d32f37bda3
--- /dev/null
+++ b/jdk/test/com/sun/net/httpserver/SimpleFileServer.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005, 2017, 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.util.*;
+import java.util.concurrent.*;
+import java.util.logging.*;
+import java.io.*;
+import java.net.*;
+import java.security.*;
+import javax.net.ssl.*;
+import com.sun.net.httpserver.*;
+
+/**
+ * Implements a basic static content HTTP server
+ * which understands text/html, text/plain content types
+ *
+ * Must be given an abs pathname to the document root.
+ * Directory listings together with text + html files
+ * can be served.
+ *
+ * File Server created on files sub-path
+ *
+ * Echo server created on echo sub-path
+ */
+public class SimpleFileServer {
+
+ public static void main (String[] args) throws Exception {
+ if (args.length != 3) {
+ System.out.println ("usage: java FileServerHandler rootDir port logfilename");
+ System.exit(1);
+ }
+ Logger logger = Logger.getLogger("com.sun.net.httpserver");
+ ConsoleHandler ch = new ConsoleHandler();
+ logger.setLevel(Level.ALL);
+ ch.setLevel(Level.ALL);
+ logger.addHandler(ch);
+
+ String rootDir = args[0];
+ int port = Integer.parseInt (args[1]);
+ String logfile = args[2];
+ HttpServer server = HttpServer.create (new InetSocketAddress (port), 0);
+ HttpHandler h = new FileServerHandler (rootDir);
+ HttpHandler h1 = new EchoHandler ();
+
+ HttpContext c = server.createContext ("/files", h);
+ c.getFilters().add (new LogFilter (new File (logfile)));
+ HttpContext c1 = server.createContext ("/echo", h1);
+ c.getFilters().add (new LogFilter (new File (logfile)));
+ c1.getFilters().add (new LogFilter (new File (logfile)));
+ server.setExecutor (Executors.newCachedThreadPool());
+ server.start ();
+ }
+}
diff --git a/jdk/test/java/net/httpclient/HttpEchoHandler.java b/jdk/test/java/net/httpclient/HttpEchoHandler.java
new file mode 100644
index 00000000000..914d89161ac
--- /dev/null
+++ b/jdk/test/java/net/httpclient/HttpEchoHandler.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, 2017, 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 com.sun.net.httpserver.*;
+import java.net.*;
+import jdk.incubator.http.*;
+import java.io.*;
+import java.util.concurrent.*;
+import javax.net.ssl.*;
+import java.nio.file.*;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import jdk.testlibrary.SimpleSSLContext;
+import static jdk.incubator.http.HttpRequest.*;
+import static jdk.incubator.http.HttpResponse.*;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class HttpEchoHandler implements HttpHandler {
+ public HttpEchoHandler() {}
+
+ @Override
+ public void handle(HttpExchange t)
+ throws IOException {
+ try {
+ System.err.println("EchoHandler received request to " + t.getRequestURI());
+ InputStream is = t.getRequestBody();
+ Headers map = t.getRequestHeaders();
+ Headers map1 = t.getResponseHeaders();
+ map1.add("X-Hello", "world");
+ map1.add("X-Bye", "universe");
+ String fixedrequest = map.getFirst("XFixed");
+ File outfile = File.createTempFile("foo", "bar");
+ FileOutputStream fos = new FileOutputStream(outfile);
+ int count = (int) is.transferTo(fos);
+ is.close();
+ fos.close();
+ InputStream is1 = new FileInputStream(outfile);
+ OutputStream os = null;
+ // return the number of bytes received (no echo)
+ String summary = map.getFirst("XSummary");
+ if (fixedrequest != null && summary == null) {
+ t.sendResponseHeaders(200, count);
+ os = t.getResponseBody();
+ is1.transferTo(os);
+ } else {
+ t.sendResponseHeaders(200, 0);
+ os = t.getResponseBody();
+ is1.transferTo(os);
+
+ if (summary != null) {
+ String s = Integer.toString(count);
+ os.write(s.getBytes());
+ }
+ }
+ outfile.delete();
+ os.close();
+ is1.close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new IOException(e);
+ }
+ }
+}
diff --git a/jdk/test/java/net/httpclient/LightWeightHttpServer.java b/jdk/test/java/net/httpclient/LightWeightHttpServer.java
index a0d6e9ac9c7..d80a382d669 100644
--- a/jdk/test/java/net/httpclient/LightWeightHttpServer.java
+++ b/jdk/test/java/net/httpclient/LightWeightHttpServer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,8 +23,9 @@
/**
* library /lib/testlibrary/ /
- * build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
+ * build jdk.testlibrary.SimpleSSLContext ProxyServer
* compile ../../../com/sun/net/httpserver/LogFilter.java
+ * compile ../../../com/sun/net/httpserver/EchoHandler.java
* compile ../../../com/sun/net/httpserver/FileServerHandler.java
*/
import com.sun.net.httpserver.Headers;
diff --git a/jdk/test/java/net/httpclient/ManyRequests.java b/jdk/test/java/net/httpclient/ManyRequests.java
index 7420c7223ed..8803b397528 100644
--- a/jdk/test/java/net/httpclient/ManyRequests.java
+++ b/jdk/test/java/net/httpclient/ManyRequests.java
@@ -28,8 +28,9 @@
* java.logging
* jdk.httpserver
* @library /lib/testlibrary/ /
- * @build jdk.testlibrary.SimpleSSLContext EchoHandler
+ * @build jdk.testlibrary.SimpleSSLContext
* @compile ../../../com/sun/net/httpserver/LogFilter.java
+ * @compile ../../../com/sun/net/httpserver/EchoHandler.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl ManyRequests
* @run main/othervm/timeout=40 -Dtest.insertDelay=true ManyRequests
diff --git a/jdk/test/java/net/httpclient/ManyRequests2.java b/jdk/test/java/net/httpclient/ManyRequests2.java
index 2ec01de9734..26c281fca61 100644
--- a/jdk/test/java/net/httpclient/ManyRequests2.java
+++ b/jdk/test/java/net/httpclient/ManyRequests2.java
@@ -28,8 +28,9 @@
* java.logging
* jdk.httpserver
* @library /lib/testlibrary/ /
- * @build jdk.testlibrary.SimpleSSLContext EchoHandler
+ * @build jdk.testlibrary.SimpleSSLContext
* @compile ../../../com/sun/net/httpserver/LogFilter.java
+ * @compile ../../../com/sun/net/httpserver/EchoHandler.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @build ManyRequests ManyRequests2
* @run main/othervm/timeout=40 -Dtest.XFixed=true ManyRequests2
diff --git a/jdk/test/java/net/httpclient/RequestBodyTest.java b/jdk/test/java/net/httpclient/RequestBodyTest.java
index fd0bbcc7aaa..446eb0324f5 100644
--- a/jdk/test/java/net/httpclient/RequestBodyTest.java
+++ b/jdk/test/java/net/httpclient/RequestBodyTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,6 +28,7 @@
* jdk.httpserver
* @library /lib/testlibrary/
* @compile ../../../com/sun/net/httpserver/LogFilter.java
+ * @compile ../../../com/sun/net/httpserver/EchoHandler.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @build LightWeightHttpServer
* @build jdk.testlibrary.SimpleSSLContext
diff --git a/jdk/test/java/net/httpclient/SmokeTest.java b/jdk/test/java/net/httpclient/SmokeTest.java
index 8d33296c390..a0636cc1df5 100644
--- a/jdk/test/java/net/httpclient/SmokeTest.java
+++ b/jdk/test/java/net/httpclient/SmokeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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 @@
* java.logging
* jdk.httpserver
* @library /lib/testlibrary/ /
- * @build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
+ * @build jdk.testlibrary.SimpleSSLContext ProxyServer
* @compile ../../../com/sun/net/httpserver/LogFilter.java
+ * @compile ../../../com/sun/net/httpserver/EchoHandler.java
* @compile ../../../com/sun/net/httpserver/FileServerHandler.java
* @run main/othervm -Djdk.httpclient.HttpClient.log=errors,trace SmokeTest
*/
diff --git a/jdk/test/java/net/httpclient/http2/BasicTest.java b/jdk/test/java/net/httpclient/http2/BasicTest.java
index 615843df973..9744eda9034 100644
--- a/jdk/test/java/net/httpclient/http2/BasicTest.java
+++ b/jdk/test/java/net/httpclient/http2/BasicTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -62,11 +62,11 @@ public class BasicTest {
sslContext = sslct.get();
client = getClient();
httpServer = new Http2TestServer(false, 0, exec, sslContext);
- httpServer.addHandler(new EchoHandler(), "/");
+ httpServer.addHandler(new Http2EchoHandler(), "/");
httpPort = httpServer.getAddress().getPort();
httpsServer = new Http2TestServer(true, 0, exec, sslContext);
- httpsServer.addHandler(new EchoHandler(), "/");
+ httpsServer.addHandler(new Http2EchoHandler(), "/");
httpsPort = httpsServer.getAddress().getPort();
httpURIString = "http://127.0.0.1:" + httpPort + "/foo/";
diff --git a/jdk/test/java/net/httpclient/http2/ErrorTest.java b/jdk/test/java/net/httpclient/http2/ErrorTest.java
index a2e115071e6..9a8815df14b 100644
--- a/jdk/test/java/net/httpclient/http2/ErrorTest.java
+++ b/jdk/test/java/net/httpclient/http2/ErrorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -83,7 +83,7 @@ public class ErrorTest {
0,
exec,
serverContext);
- httpsServer.addHandler(new EchoHandler(), "/");
+ httpsServer.addHandler(new Http2EchoHandler(), "/");
int httpsPort = httpsServer.getAddress().getPort();
String httpsURIString = "https://127.0.0.1:" + httpsPort + "/bar/";
diff --git a/jdk/test/java/net/httpclient/http2/FixedThreadPoolTest.java b/jdk/test/java/net/httpclient/http2/FixedThreadPoolTest.java
index 39676149e3a..d6de84aca6c 100644
--- a/jdk/test/java/net/httpclient/http2/FixedThreadPoolTest.java
+++ b/jdk/test/java/net/httpclient/http2/FixedThreadPoolTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -62,11 +62,11 @@ public class FixedThreadPoolTest {
sslContext = sslct.get();
client = getClient();
httpServer = new Http2TestServer(false, 0, exec, sslContext);
- httpServer.addHandler(new EchoHandler(), "/");
+ httpServer.addHandler(new Http2EchoHandler(), "/");
httpPort = httpServer.getAddress().getPort();
httpsServer = new Http2TestServer(true, 0, exec, sslContext);
- httpsServer.addHandler(new EchoHandler(), "/");
+ httpsServer.addHandler(new Http2EchoHandler(), "/");
httpsPort = httpsServer.getAddress().getPort();
httpURIString = "http://127.0.0.1:" + httpPort + "/foo/";
diff --git a/jdk/test/java/net/httpclient/http2/RedirectTest.java b/jdk/test/java/net/httpclient/http2/RedirectTest.java
index 634467e06e1..cf0278585f3 100644
--- a/jdk/test/java/net/httpclient/http2/RedirectTest.java
+++ b/jdk/test/java/net/httpclient/http2/RedirectTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -79,7 +79,7 @@ public class RedirectTest {
httpServer.addHandler(new RedirectHandler(sup(altURIString1)), "/foo");
altServer.addHandler(new RedirectHandler(sup(altURIString2)), "/redir");
- altServer.addHandler(new EchoHandler(), "/redir/again");
+ altServer.addHandler(new Http2EchoHandler(), "/redir/again");
httpServer.start();
altServer.start();
diff --git a/jdk/test/java/net/httpclient/http2/server/Http2EchoHandler.java b/jdk/test/java/net/httpclient/http2/server/Http2EchoHandler.java
new file mode 100644
index 00000000000..c1ebebe0d2f
--- /dev/null
+++ b/jdk/test/java/net/httpclient/http2/server/Http2EchoHandler.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005, 2017, 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.io.*;
+import jdk.incubator.http.internal.common.HttpHeadersImpl;
+
+public class Http2EchoHandler implements Http2Handler {
+ public Http2EchoHandler() {}
+
+ @Override
+ public void handle(Http2TestExchange t)
+ throws IOException {
+ try {
+ System.err.println("EchoHandler received request to " + t.getRequestURI());
+ InputStream is = t.getRequestBody();
+ HttpHeadersImpl map = t.getRequestHeaders();
+ HttpHeadersImpl map1 = t.getResponseHeaders();
+ map1.addHeader("X-Hello", "world");
+ map1.addHeader("X-Bye", "universe");
+ String fixedrequest = map.firstValue("XFixed").orElse(null);
+ File outfile = File.createTempFile("foo", "bar");
+ //System.err.println ("QQQ = " + outfile.toString());
+ FileOutputStream fos = new FileOutputStream(outfile);
+ int count = (int) is.transferTo(fos);
+ System.err.printf("EchoHandler read %d bytes\n", count);
+ is.close();
+ fos.close();
+ InputStream is1 = new FileInputStream(outfile);
+ OutputStream os = null;
+ // return the number of bytes received (no echo)
+ String summary = map.firstValue("XSummary").orElse(null);
+ if (fixedrequest != null && summary == null) {
+ t.sendResponseHeaders(200, count);
+ os = t.getResponseBody();
+ int count1 = (int)is1.transferTo(os);
+ System.err.printf("EchoHandler wrote %d bytes\n", count1);
+ } else {
+ t.sendResponseHeaders(200, 0);
+ os = t.getResponseBody();
+ int count1 = (int)is1.transferTo(os);
+ System.err.printf("EchoHandler wrote %d bytes\n", count1);
+
+ if (summary != null) {
+ String s = Integer.toString(count);
+ os.write(s.getBytes());
+ }
+ }
+ outfile.delete();
+ os.close();
+ is1.close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new IOException(e);
+ }
+ }
+}
From 70eda1ba26e0b330547c5943a6e9e093bf9238f5 Mon Sep 17 00:00:00 2001
From: Paul Sandoz The stream binds to this bit set when the terminal stream operation
* commences (specifically, the spliterator for the stream is
- * late-binding). If the
+ * late-binding). If the
* bit set is modified during that operation then the result is undefined.
*
* @return a stream of integers representing set indices
From 2844bc771c0dcdf3e953678409db0f3389a6dc47 Mon Sep 17 00:00:00 2001
From: Lana Steuck Last updated 2015-03-06 (Added java.datatransfer. Assumes JNLP is modularized, and StAX joins the Java SE Platform.) Last updated 2017-06-08 JDK Module Summary | Technologies in the Java SE Documentation JDK 9 Module Summary | Technologies in the Java SE 8 Documentation An upgradeable module contains JCP technology that is in the Java SE Platform but is not exclusive to the Java SE Platform, i.e., the green and pink technologies. Most upgradeable modules are defined by loaders other than the bootstrap. Class loaders may typically be used by security managers to indicate
* security domains.
*
+ * In addition to loading classes, a class loader is also responsible for
+ * locating resources. A resource is some data (a "{@code .class}" file,
+ * configuration data, or an image for example) that is identified with an
+ * abstract '/'-separated path name. Resources are typically packaged with an
+ * application or library so that they can be located by code in the
+ * application or library. In some cases, the resources are included so that
+ * they can be located by other libraries.
+ *
* The {@code ClassLoader} class uses a delegation model to search for
* classes and resources. Each instance of {@code ClassLoader} has an
- * associated parent class loader. When requested to find a class or
- * resource, a {@code ClassLoader} instance will delegate the search for the
- * class or resource to its parent class loader before attempting to find the
- * class or resource itself.
+ * associated parent class loader. When requested to find a class or
+ * resource, a {@code ClassLoader} instance will usually delegate the search
+ * for the class or resource to its parent class loader before attempting to
+ * find the class or resource itself.
*
* Class loaders that support concurrent loading of classes are known as
* {@linkplain #isRegisteredAsParallelCapable() parallel capable} class
@@ -129,11 +137,13 @@ import sun.security.util.SecurityConstants;
* classes and JDK-specific run-time classes that are defined by the
* platform class loader or its ancestors.
* To allow for upgrading/overriding of modules defined to the platform
- * class loader, and where classes in the upgraded version link to
- * classes in modules defined to the application class loader, the
- * platform class loader may delegate to the application class loader.
- * In other words, classes in named modules defined to the application
- * class loader may be visible to the platform class loader.
+ * class loader, and where upgraded modules read modules defined to class
+ * loaders other than the platform class loader and its ancestors, then
+ * the platform class loader may have to delegate to other class loaders,
+ * the application class loader for example.
+ * In other words, classes in named modules defined to class loaders
+ * other than the platform class loader and its ancestors may be visible
+ * to the platform class loader.
* {@linkplain #getSystemClassLoader() System class loader}.
* It is also known as application class loader and is distinct
* from the platform class loader.
@@ -498,7 +508,7 @@ public abstract class ClassLoader {
*
* Invoke the {@link #loadClass(String) loadClass} method
* on the parent class loader. If the parent is {@code null} the class
- * loader built-in to the virtual machine is used, instead. Invoke the {@link #findClass(String)} method to find the
* class. The name of a resource is a '{@code /}'-separated path name that
- * identifies the resource.
- *
- * This method will first search the parent class loader for the
- * resource; if the parent is {@code null} the path of the class loader
- * built-in to the virtual machine is searched. That failing, this method
- * will invoke {@link #findResource(String)} to find the resource. Resources in named modules are subject to the encapsulation rules
* specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
@@ -1344,6 +1351,11 @@ public abstract class ClassLoader {
* opened} unconditionally (even if the caller of this method is in the
* same module as the resource). The name of a resource is a {@code /}-separated path name that
- * identifies the resource.
- *
- * The delegation order for searching is described in the documentation
- * for {@link #getResource(String)}. Directory listing for: " + path+ "
");
+ p.println ("");
+ for (int i=0; i
");
+ p.flush();
+ p.close();
+ } else {
+ int clen;
+ if (fixedrequest != null) {
+ clen = (int) f.length();
} else {
- rmap.set ("Content-Type", "text/plain");
+ clen = 0;
}
- if (f.isDirectory()) {
- if (!path.endsWith ("/")) {
- moved (t);
- return;
- }
- rmap.set ("Content-Type", "text/html");
- t.sendResponseHeaders (200, 0);
- String[] list = f.list();
- OutputStream os = t.getResponseBody();
- PrintStream p = new PrintStream (os);
- p.println ("Directory listing for: " + path+ "
");
- p.println ("");
- for (int i=0; i
");
- p.flush();
- p.close();
- } else {
- int clen;
- if (fixedrequest != null) {
- clen = (int) f.length();
- } else {
- clen = 0;
- }
- t.sendResponseHeaders (200, clen);
- OutputStream os = t.getResponseBody();
- FileInputStream fis = new FileInputStream (f);
- int count = 0;
- try {
+ t.sendResponseHeaders (200, clen);
+ OutputStream os = t.getResponseBody();
+ FileInputStream fis = new FileInputStream (f);
+ int count = 0;
+ try {
byte[] buf = new byte [16 * 1024];
int len;
while ((len=fis.read (buf)) != -1) {
os.write (buf, 0, len);
count += len;
}
- } catch (IOException e) {
- e.printStackTrace();
- }
- fis.close();
- os.close();
+ } catch (IOException e) {
+ e.printStackTrace();
}
- }
-
- void moved (HttpExchange t) throws IOException {
- Headers req = t.getRequestHeaders();
- Headers map = t.getResponseHeaders();
- URI uri = t.getRequestURI();
- String host = req.getFirst ("Host");
- String location = "http://"+host+uri.getPath() + "/";
- map.set ("Content-Type", "text/html");
- map.set ("Location", location);
- t.sendResponseHeaders (301, -1);
- t.close();
- }
-
- void notfound (HttpExchange t, String p) throws IOException {
- t.getResponseHeaders().set ("Content-Type", "text/html");
- t.sendResponseHeaders (404, 0);
- OutputStream os = t.getResponseBody();
- String s = "File not found
";
- s = s + p + "File not found
";
+ s = s + p + "JCP Technologies in the Modular JDK
+JCP Technologies in JDK 9
-
-Legend JCP technology in the Java SE Platform only -- in java.base
-JCP technology in the Java SE Platform only -- not in java.base
-JCP technology in the Java SE Platform and the Java EE Platform
-JCP technology in the Java SE Platform based on non-JCP standards
+JCP technology in neither the Java SE or EE Platforms
+JCP technology in the Java SE Platform derived from the Java EE Platform
+JCP technology in the Java SE Platform derived from non-JCP standards JCP technology in neither the Java SE or EE Platforms
diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java
index e6962ac45ec..679c0fa1066 100644
--- a/jdk/src/java.base/share/classes/java/lang/Class.java
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java
@@ -50,6 +50,7 @@ import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -2066,25 +2067,6 @@ public final class Class
+
-
-JSR
Technology
-Original JSR
-Original Target
+Evolved By
Module
-Evolved By
-History
-Profile/SE
Loader
Upg?
-
-
-
-JMX
-3
-Java SE
-java.management
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-Print Service
-6
-Java SE
-java.desktop
-UJSR for Java SE
-
- SE
-boot
-No
-
-
-
-Preferences
-10
-Java SE
-java.prefs
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-Image I/O
-15
-Java SE
-java.desktop
-UJSR for Java SE
-
- SE
-boot
-No
-
-
-
-SASL
-28
-Java SE
-java.security.sasl
-UJSR for Java SE
-
- 3
-boot
-No
-
-
Logging
-47
-Java SE
-java.logging
-UJSR for Java SE
-
- 1
-boot
-No
+Notes
+Aggregator
-
-
-NIO
-51
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-JNLP
-56
-Java SE
-java.jnlp
-Original JSR
-
- N/A
-boot
-No
-
-
-
-Beans Persistence
-57
-Java SE
-java.desktop
-UJSR for Java SE
-
- SE
-boot
-No
-
-
-
-GSS
-72
-Java SE
-java.security.jgss
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-XML Digital Signature
-105
-Java SE
-java.xml.crypto
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-JDBC Rowset
-114
-Java SE
-java.sql.rowset
-Original JSR
-Co-evolved with JDBC
-3
-boot
-No
-
-
-
-JMX Remote
-160
-Java SE
-java.management
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-Profiling (Agent)
-163
-Java SE
-java.instrument
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-Profiling (JMX)
-163
-Java SE
-java.management
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-Concurrency Utilities
-166
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-Annotations
-175
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-StAX
-173
-Java SE
-java.xml
-Original JSR
-Formerly a Standalone Technology
-2
-boot
-No
-
-
-
-Annotations (Language Model)
-175
-Java SE
-java.compiler
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-Compiler
-199
-Java SE
-java.compiler
-Original JSR
-Formerly a Standalone Technology
-3
-boot
-No
-
-
-
-Pack200
-200
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-NIO.2
-203
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-JAXP
-206
-Java SE
-java.xml
-UJSR for Java SE
-Formerly a Standalone Technology
-2
-boot
-No
-
-
-
-JDBC
-221
-Java SE
-java.sql
-Original JSR
-Co-evolved with JDBC Rowset
-2
-boot
-No
-
-
-
-Scripting
-223
-Java SE
-java.scripting
-Original JSR
-Formerly a Standalone Technology
-1
-boot
-No
-
-
-
-Smart Card I/O
-268
-Java SE
-java.smartcardio
-Original JSR
-Formerly a Standalone Technology (unlisted)
-N/A
-boot
-No
-
-
-
-Annotation Processing
-269
-Java SE
-java.compiler
-Original JSR
-Formerly a Standalone Technology
-3
-boot
-No
-
-
-
-InvokeDynamic
-292
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-Type Annotations
-308
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-Type Annotations (Language Model)
-308
-Java SE
-java.compiler
-UJSR for Java SE
-
- 3
-boot
-No
-
-
-
-Date and Time
-310
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-Streams
-335
-Java SE
-java.base
-UJSR for Java SE
-
- 1
-boot
-No
-
-
-
-Collections, Math, I18N, I/O, Net, Reflection
---
----
-java.base
+Collections, Concurrency,
Core Reflection, I18N, I/O,
JAAS, JCA, JSSE, Math, Net, TextUJSR for Java SE
-
- 1
+java.base
boot
No
-
-
JCA, JAAS, JSSE
----
----
-java.base
-UJSR for Java SE
- 1
-boot
-No
+java.se
-
Applet, AWT, Swing, Java 2D, Beans, A11Y, Sound
----
---
+A11Y, Applet, AWT, Beans,
+
Image I/O, Java 2D,
Print, Sound, SwingUJSR for Java SE
java.desktop
-UJSR for Java SE
-
- SE
boot
No
+
+
---
Data Transfer
----
----
+UJSR for Java SE
java.datatransfer
-UJSR for Java SE
-
- SE
boot
No
+
+
---
JNDI
----
----
+UJSR for Java SE
java.naming
-UJSR for Java SE
-
- 3
boot
No
+
+
---
RMI
----
----
-java.rmi
UJSR for Java SE
-
- 2
+java.rmi
boot
No
+
-
-
-JAF
-925
----
-java.activation
-Original JSR
-Formerly a Standalone Technology (unlisted)
-SE
-ext
-Yes
-
-
-RMI-IIOP, IDL
-(OMG)
----
-java.corba
+3
+JMX
UJSR for Java SE
-Formerly an Endorsed Standard
-SE
-ext
-Yes
+java.management
+boot
+No
+
- DOM, SAX
-(W3C)
----
+
+
+
+6
+Print Service
+UJSR for Java SE
+java.desktop
+boot
+No
+
+
+
+
+10
+Preferences
+UJSR for Java SE
+java.prefs
+boot
+No
+
+
+
+
+15
+Image I/O
+UJSR for Java SE
+java.desktop
+boot
+No
+
+
+
+
+28
+SASL
+UJSR for Java SE
+java.security.sasl
+boot
+No
+
+
+
+
+47
+Logging
+UJSR for Java SE
+java.logging
+boot
+No
+
+
+
+
+51
+NIO
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+57
+Beans Persistence
+UJSR for Java SE
+java.desktop
+boot
+No
+
+
+
+
+72
+GSS
+UJSR for Java SE
+java.security.jgss
+plat
+No
+
+
+
+
+105
+XML Digital Signature
+UJSR for Java SE
+java.xml.crypto
+plat
+No
+
+
+
+
+114
+JDBC Rowset
+Original JSR
+java.sql.rowset
+plat
+No
+Co-developed with JDBC
+
+
+
+160
+JMX Remote
+UJSR for Java SE
+java.management
+boot
+No
+
+
+
+
+
+160
+JMX Remote (RMI)
+UJSR for Java SE
+java.management.rmi
+boot
+No
+
+
+
+
+163
+Instrumentation
+UJSR for Java SE
+java.instrument
+boot
+No
+Co-developed with JVMTI
+
+
+
+163
+Monitoring & Management
+UJSR for Java SE
+java.management
+boot
+No
+
+
+
+
+166
+Concurrency Utilities
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+173
+StAX
+UJSR for Java SE
java.xml
+boot
+No
+Formerly a Standalone Technology
+
+
+
+175
+Annotations (Core Reflection)
UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+175
+Annotations (Language Model)
+UJSR for Java SE
+java.compiler
+plat
+Yes
+Co-located with a former Standalone Technology
+
+
+
+199
+Compiler
+Original JSR
+java.compiler
+plat
+Yes
+Formerly a Standalone Technology
+
+
+
+200
+Pack200
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+203
+NIO.2
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+206
+JAXP
+UJSR for Java SE
+java.xml
+boot
+No
+Formerly a Standalone Technology
+
+
+
+221
+JDBC
+Original JSR
+java.sql
+plat
+No
+Co-developed with JDBC Rowset
+
+
+
+223
+Scripting
+UJSR for Java SE
+java.scripting
+plat
+No
+Formerly a Standalone Technology
+
+
+
+269
+Annotation Processing
+Original JSR
+java.compiler
+plat
+Yes
+Formerly a Standalone Technology
+
+
+
+292
+InvokeDynamic
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+308
+Type Annotations (Core Reflection)
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+308
+Type Annotations (Language Model)
+UJSR for Java SE
+java.compiler
+plat
+Yes
+Co-located with a former Standalone Technology
+
+
+
+310
+Date and Time
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+335
+Streams
+UJSR for Java SE
+java.base
+boot
+No
+
+
+
+
+(W3C)
+DOM, SAX
+UJSR for Java SE
+java.xml
+boot
+No
Formerly an Endorsed Standard
-2
-boot
-No
+
+
(OMG)
+RMI-IIOP, IDL
+UJSR for Java SE
+java.corba
+plat
+Yes
+Formerly an Endorsed Standard
+java.se.ee
-
SAAJ
67
-Java SE
-java.xml.ws
+SAAJ
Original JSR
+java.xml.ws
+plat
+Yes
Formerly a Standalone Technology (f.k.a. JAXM)
-SE
-ext
-Yes
-
Web Services Metadata
181
-Java EE
-java.xml.ws
+Web Services Metadata
Original JSR
-Formerly a Standalone Technology (unlisted)
-SE
-ext
+java.xml.ws
+plat
Yes
+Formerly a Standalone Technology (unlisted)
-
JAXB
222
-Java SE
+JAXB
+Original JSR
java.xml.bind
-Original JSR
-Formerly a Standalone Technology
-SE
-ext
+plat
Yes
+Formerly a Standalone Technology
-
-
+
JAXWS
224
-Java SE
+JAXWS
+Original JSR
java.xml.ws
-Original JSR
+plat
+Yes
Formerly a Standalone Technology
-SE
-ext
-Yes
-
-
+
Common Annotations
250
-Java SE,EE
+Common Annotations
+Original JSR
java.xml.ws.annotation
-Original JSR
-Formerly a Standalone Technology (unlisted)
-SE
-ext
+plat
Yes
+Formerly a Standalone Technology (unlisted)
+
-
+
907
JTA (non-XA)
-907
----
-java.transaction
Original JSR
-Formerly a Standalone Technology (unlisted)
-SE
-ext
+java.transaction
+plat
Yes
+Formerly a Standalone Technology (unlisted)
-
+
+JTA (XA)
907
----
-java.sql
+JTA (XA)
Original JSR
-Formerly a Standalone Technology (unlisted)
-2
-boot
+java.sql
+plat
No
+Formerly a Standalone Technology (unlisted)
+java.se
+
+
+
+925
+JAF
+Original JSR
+java.activation
+plat
+Yes
+Formerly a Standalone Technology (unlisted)
+java.se.ee
+
+
+
+56
+JNLP
+Original JSR
+java.jnlp
+plat
+Yes
+
+ None
+
+
268
+Smart Card I/O
+Original JSR
+java.smartcardio
+plat
+No
+Formerly a Standalone Technology (unlisted)
Resources in named modules are subject to the encapsulation rules * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}. @@ -1398,7 +1407,15 @@ public abstract class ClassLoader { * name ending with "{@code .class}", this method will only find resources in * packages of named modules when the package is {@link Module#isOpen(String) * opened} unconditionally (even if the caller of this method is in the - * same module as the resource).
+ * same module as the resource). + * + * @implSpec The default implementation will first search the parent class + * loader for the resource; if the parent is {@code null} the path of the + * class loader built into the virtual machine is searched. It then + * invokes {@link #findResources(String)} to find the resources with the + * name in this class loader. It returns an enumeration whose elements + * are the URLs found by searching the parent class loader followed by + * the elements found with {@code findResources}. * * @apiNote Where several modules are defined to the same class loader, * and where more than one module contains a resource with the given name, @@ -1424,8 +1441,6 @@ public abstract class ClassLoader { * If I/O errors occur * @throws NullPointerException If {@code name} is {@code null} * - * @see #findResources(String) - * * @since 1.2 * @revised 9 * @spec JPMS @@ -1453,9 +1468,6 @@ public abstract class ClassLoader { *The name of a resource is a {@code /}-separated path name that * identifies the resource. * - *
The search order is described in the documentation for {@link - * #getResource(String)}. - * *
The resources will be located when the returned stream is evaluated. * If the evaluation results in an {@code IOException} then the I/O * exception is wrapped in an {@link UncheckedIOException} that is then @@ -1469,6 +1481,10 @@ public abstract class ClassLoader { * opened} unconditionally (even if the caller of this method is in the * same module as the resource).
* + * @implSpec The default implementation invokes {@link #getResources(String) + * getResources} to find all the resources with the given name and returns + * a stream with the elements in the enumeration as the source. + * * @apiNote When overriding this method it is recommended that an * implementation ensures that any delegation is consistent with the {@link * #getResource(java.lang.String) getResource(String)} method. This should @@ -1486,8 +1502,6 @@ public abstract class ClassLoader { * * @throws NullPointerException If {@code name} is {@code null} * - * @see #findResources(String) - * * @since 9 */ public StreamFor resources in named modules then the method must implement the * rules for encapsulation specified in the {@code Module} {@link @@ -1515,6 +1529,8 @@ public abstract class ClassLoader { * modules unless the package is {@link Module#isOpen(String) opened} * unconditionally.
* + * @implSpec The default implementation returns {@code null}. + * * @param name * The resource name * @@ -1535,8 +1551,7 @@ public abstract class ClassLoader { /** * Returns an enumeration of {@link java.net.URL URL} objects * representing all the resources with the given name. Class loader - * implementations should override this method to specify where to load - * resources from. + * implementations should override this method. * *For resources in named modules then the method must implement the * rules for encapsulation specified in the {@code Module} {@link @@ -1545,6 +1560,9 @@ public abstract class ClassLoader { * modules unless the package is {@link Module#isOpen(String) opened} * unconditionally.
* + * @implSpec The default implementation returns an enumeration that + * contains no elements. + * * @param name * The resource name * @@ -1899,7 +1917,8 @@ public abstract class ClassLoader { // the system class loader is the built-in app class loader during startup return getBuiltinAppClassLoader(); case 3: - throw new InternalError("getSystemClassLoader should only be called after VM booted"); + String msg = "getSystemClassLoader should only be called after VM booted"; + throw new InternalError(msg); case 4: // system fully initialized assert VM.isBooted() && scl != null; diff --git a/jdk/src/java.base/share/classes/java/lang/LayerInstantiationException.java b/jdk/src/java.base/share/classes/java/lang/LayerInstantiationException.java index 4c64fe071a8..5a7ee0aaaac 100644 --- a/jdk/src/java.base/share/classes/java/lang/LayerInstantiationException.java +++ b/jdk/src/java.base/share/classes/java/lang/LayerInstantiationException.java @@ -63,8 +63,8 @@ public class LayerInstantiationException extends RuntimeException { } /** - * Constructs a {@code FindException} with the given detail message - * and cause. + * Constructs a {@code LayerInstantiationException} with the given detail + * message and cause. * * @param msg * The detail message; can be {@code null} @@ -74,6 +74,5 @@ public class LayerInstantiationException extends RuntimeException { public LayerInstantiationException(String msg, Throwable cause) { super(msg, cause); } - } diff --git a/jdk/src/java.base/share/classes/java/lang/Module.java b/jdk/src/java.base/share/classes/java/lang/Module.java index f6ab49b4519..2b1e0ed74a6 100644 --- a/jdk/src/java.base/share/classes/java/lang/Module.java +++ b/jdk/src/java.base/share/classes/java/lang/Module.java @@ -43,6 +43,7 @@ import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -55,8 +56,10 @@ import java.util.stream.Stream; import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.BootLoader; +import jdk.internal.loader.ClassLoaders; import jdk.internal.misc.JavaLangAccess; import jdk.internal.misc.SharedSecrets; +import jdk.internal.module.IllegalAccessLogger; import jdk.internal.module.ModuleLoaderMap; import jdk.internal.module.ServicesCatalog; import jdk.internal.module.Resources; @@ -162,7 +165,6 @@ public final class Module implements AnnotatedElement { } - /** * Returns {@code true} if this module is a named module. * @@ -249,12 +251,10 @@ public final class Module implements AnnotatedElement { // special Module to mean "all unnamed modules" private static final Module ALL_UNNAMED_MODULE = new Module(null); + private static final SetThe class loader created by this method implements direct - * delegation when loading types from modules. When its {@link + * delegation when loading classes from modules. If the {@link * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to * load a class then it uses the package name of the class to map it to a * module. This may be a module in this layer and hence defined to the same @@ -408,6 +434,12 @@ public final class ModuleLayer { * When {@code loadClass} is invoked to load classes that do not map to a * module then it delegates to the parent class loader.
* + *The class loader created by this method locates resources + * ({@link ClassLoader#getResource(String) getResource}, {@link + * ClassLoader#getResources(String) getResources}, and other resource + * methods) in all modules in the layer before searching the parent class + * loader.
+ * *Attempting to create a layer with all modules defined to the same * class loader can fail for the following reasons: * @@ -417,8 +449,8 @@ public final class ModuleLayer { * configuration have the same package.
* *Split delegation: The resulting class loader would - * need to delegate to more than one class loader in order to load types - * in a specific package.
The class loaders created by this method implement direct - * delegation when loading types from modules. When {@link + * delegation when loading classes from modules. If the {@link * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to * load a class then it uses the package name of the class to map it to a * module. The package may be in the module defined to the class loader. @@ -489,9 +521,15 @@ public final class ModuleLayer { * module defined to the class loader. It may be in a package exported by a * module in a parent layer. The class loader delegates to the class loader * of the module, throwing {@code ClassNotFoundException} if not found by - * that class loader. - * When {@code loadClass} is invoked to load classes that do not map to a - * module then it delegates to the parent class loader.
+ * that class loader. When {@code loadClass} is invoked to load a class + * that does not map to a module then it delegates to the parent class + * loader. + * + *The class loaders created by this method locate resources + * ({@link ClassLoader#getResource(String) getResource}, {@link + * ClassLoader#getResources(String) getResources}, and other resource + * methods) in the module defined to the class loader before searching + * the parent class loader.
* *If there is a security manager then the class loaders created by * this method will load classes and resources with privileges that are @@ -576,10 +614,9 @@ public final class ModuleLayer { *
In addition, a layer cannot be created if the configuration contains * a module named "{@code java.base}", a configuration contains a module * with a package named "{@code java}" or a package name starting with - * "{@code java.}" and the module is mapped to a class loader other than - * the {@link ClassLoader#getPlatformClassLoader() platform class loader}, - * or the function to map a module name to a class loader returns - * {@code null}.
+ * "{@code java.}", or the function to map a module name to a class loader + * returns {@code null} or the {@linkplain ClassLoader#getPlatformClassLoader() + * platform class loader}. * * If the function to map a module name to class loader throws an error
* or runtime exception then it is propagated to the caller of this method.
diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java
index 10664819e4f..c8d807a3d13 100644
--- a/jdk/src/java.base/share/classes/java/lang/System.java
+++ b/jdk/src/java.base/share/classes/java/lang/System.java
@@ -47,6 +47,8 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
@@ -2067,8 +2069,8 @@ public final class System {
private static void setJavaLangAccess() {
// Allow privileged classes outside of java.lang
SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
- public Method getMethodOrNull(Class> klass, String name, Class>... parameterTypes) {
- return klass.getMethodOrNull(name, parameterTypes);
+ public List A configuration encapsulates the readability graph that is the
- * output of resolution. A readability graph is a directed graph where the nodes
+ * output of resolution. A readability graph is a directed graph whose vertices
* are of type {@link ResolvedModule} and the edges represent the readability
* amongst the modules. {@code Configuration} defines the {@link #modules()
* modules()} method to get the set of resolved modules in the graph. {@code
@@ -176,8 +175,8 @@ public final class Configuration {
* If resolution fails for any of the observability-related reasons
* specified by the static {@code resolve} method
* @throws ResolutionException
- * If any of the post-resolution consistency checks specified by
- * the static {@code resolve} method fail
+ * If resolution fails any of the consistency checks specified by
+ * the static {@code resolve} method
* @throws SecurityException
* If locating a module is denied by the security manager
*/
@@ -219,8 +218,8 @@ public final class Configuration {
* If resolution fails for any of the observability-related reasons
* specified by the static {@code resolve} method
* @throws ResolutionException
- * If any of the post-resolution consistency checks specified by
- * the static {@code resolve} method fail
+ * If resolution fails any of the consistency checks specified by
+ * the static {@code resolve} method
* @throws SecurityException
* If locating a module is denied by the security manager
*/
@@ -234,7 +233,7 @@ public final class Configuration {
/**
* Resolves a collection of root modules, with service binding, and with
- * the empty configuration as its parent. The post resolution checks
+ * the empty configuration as its parent. The consistency checks
* are optionally run.
*
* This method is used to create the configuration for the boot layer.
@@ -264,10 +263,9 @@ public final class Configuration {
* or dependences that are located in a parent configuration are resolved
* no further and are not included in the resulting configuration. When all modules have been resolved then the resulting dependency
- * graph is checked to ensure that it does not contain cycles. A
- * readability graph is constructed, and in conjunction with the module
- * exports and service use, checked for consistency. When all modules have been enumerated then a readability graph
+ * is computed, and in conjunction with the module exports and service use,
+ * checked for consistency. Resolution may fail with {@code FindException} for the following
* observability-related reasons: Post-resolution consistency checks may fail with {@code
- * ResolutionException} for the following reasons: Resolution may fail with {@code ResolutionException} if any of the
+ * following consistency checks fail:
*
@@ -329,9 +327,11 @@ public final class Configuration {
* root modules
*
* @throws FindException
- * If resolution fails for an observability-related reason
+ * If resolution fails for any of observability-related reasons
+ * specified above
* @throws ResolutionException
- * If a post-resolution consistency checks fails
+ * If resolution fails for any of the consistency checks specified
+ * above
* @throws IllegalArgumentException
* If the list of parents is empty, or the list has two or more
* parents with modules for different target operating systems,
@@ -368,11 +368,11 @@ public final class Configuration {
* resolve} except that the graph of resolved modules is augmented
* with modules induced by the service-use dependence relation.
More specifically, the root modules are resolved as if by calling - * {@code resolve}. The resolved modules, and all modules in the - * parent configurations, with {@link ModuleDescriptor#uses() service - * dependences} are then examined. All modules found by the given module - * finders that {@link ModuleDescriptor#provides() provide} an + *
More specifically, the root modules are + * resolved as if by calling {@code resolve}. The resolved modules, and + * all modules in the parent configurations, with {@link ModuleDescriptor#uses() + * service dependences} are then examined. All modules found by the given + * module finders that {@link ModuleDescriptor#provides() provide} an * implementation of one or more of the service types are added to the * module graph and then resolved as if by calling the {@code * resolve} method. Adding modules to the module graph may introduce new @@ -402,8 +402,8 @@ public final class Configuration { * If resolution fails for any of the observability-related reasons * specified by the static {@code resolve} method * @throws ResolutionException - * If any of the post-resolution consistency checks specified by - * the static {@code resolve} method fail + * If resolution fails any of the consistency checks specified by + * the static {@code resolve} method * @throws IllegalArgumentException * If the list of parents is empty, or the list has two or more * parents with modules for different target operating systems, diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java index e0e6d883550..5a8b8cb63f3 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java @@ -48,7 +48,7 @@ import jdk.internal.module.SystemModuleFinder; /** * A finder of modules. A {@code ModuleFinder} is used to find modules during * resolution or - * service binding. + * service binding. * *
A {@code ModuleFinder} can only find one module with a given name. A * {@code ModuleFinder} that finds modules in a sequence of directories, for @@ -239,30 +239,35 @@ public interface ModuleFinder { * *
The module {@link ModuleDescriptor#name() name}, and {@link - * ModuleDescriptor#version() version} if applicable, is derived from - * the file name of the JAR file as follows:
+ *If the JAR file has the attribute "{@code Automatic-Module-Name}" + * in its main manifest then its value is the {@linkplain + * ModuleDescriptor#name() module name}. The module name is otherwise + * derived from the name of the JAR file.
The {@link ModuleDescriptor#version() version}, and the + * module name when the attribute "{@code Automatic-Module-Name}" is not + * present, are derived from the file name of the JAR file as follows:
* *The {@code .jar} suffix is removed.
The "{@code .jar}" suffix is removed.
If the name matches the regular expression {@code * "-(\\d+(\\.|$))"} then the module name will be derived from the * subsequence preceding the hyphen of the first occurrence. The * subsequence after the hyphen is parsed as a {@link - * ModuleDescriptor.Version} and ignored if it cannot be parsed as - * a {@code Version}.
All non-alphanumeric characters ({@code [^A-Za-z0-9]}) * in the module name are replaced with a dot ({@code "."}), all * repeating dots are replaced with one dot, and all leading and * trailing dots are removed.
As an example, a JAR file named {@code foo-bar.jar} will - * derive a module name {@code foo.bar} and no version. A JAR file - * named {@code foo-bar-1.2.3-SNAPSHOT.jar} will derive a module - * name {@code foo.bar} and {@code 1.2.3-SNAPSHOT} as the version. + *
As an example, a JAR file named "{@code foo-bar.jar}" will + * derive a module name "{@code foo.bar}" and no version. A JAR file + * named "{@code foo-bar-1.2.3-SNAPSHOT.jar}" will derive a module + * name "{@code foo.bar}" and "{@code 1.2.3-SNAPSHOT}" as the version. *
If a {@code ModuleDescriptor} cannot be created (by means of the * {@link ModuleDescriptor.Builder ModuleDescriptor.Builder} API) for an * automatic module then {@code FindException} is thrown. This can arise - * when a legal module name cannot be derived from the file name of the JAR - * file, where the JAR file contains a {@code .class} in the top-level - * directory of the JAR file, where an entry in a service configuration - * file is not a legal class name or its package name is not in the set of - * packages derived for the module.
+ * when the value of the "{@code Automatic-Module-Name}" attribute is not a + * legal module name, a legal module name cannot be derived from the file + * name of the JAR file, where the JAR file contains a {@code .class} in + * the top-level directory of the JAR file, where an entry in a service + * configuration file is not a legal class name or its package name is not + * in the set of packages derived for the module. * *In addition to JAR files, an implementation may also support modules * that are packaged in other implementation specific module formats. If diff --git a/jdk/src/java.base/share/classes/java/lang/module/package-info.java b/jdk/src/java.base/share/classes/java/lang/module/package-info.java index c8e2c04d975..902019b8ce4 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/package-info.java +++ b/jdk/src/java.base/share/classes/java/lang/module/package-info.java @@ -27,118 +27,178 @@ * Classes to support module descriptors and creating configurations of modules * by means of resolution and service binding. * - *
Resolution is the process of computing the transitive closure of a set - * of root modules over a set of observable modules by resolving the - * dependences expressed by {@link - * java.lang.module.ModuleDescriptor.Requires requires} clauses. - * The dependence graph is augmented with edges that take account of - * implicitly declared dependences ({@code requires transitive}) to create a - * readability graph. The result of resolution is a {@link - * java.lang.module.Configuration Configuration} that encapsulates the - * readability graph.
- * - *As an example, suppose we have the following observable modules:
- *{@code - * module m1 { requires m2; } - * module m2 { requires transitive m3; } - * module m3 { } - * module m4 { } - * }- * - *
If the module {@code m1} is resolved then the resulting configuration - * contains three modules ({@code m1}, {@code m2}, {@code m3}). The edges in - * its readability graph are:
- *{@code - * m1 --> m2 (meaning m1 reads m2) - * m1 --> m3 - * m2 --> m3 - * }- * - *
Resolution is an additive process. When computing the transitive closure - * then the dependence relation may include dependences on modules in {@link - * java.lang.module.Configuration#parents() parent} configurations. The result - * is a relative configuration that is relative to one or more parent - * configurations and where the readability graph may have edges from modules - * in the configuration to modules in parent configurations.
- * - *As an example, suppose we have the following observable modules:
- *{@code - * module m1 { requires m2; requires java.xml; } - * module m2 { } - * }- * - *
If module {@code m1} is resolved with the configuration for the {@link - * java.lang.ModuleLayer#boot() boot} layer as the parent then the resulting - * configuration contains two modules ({@code m1}, {@code m2}). The edges in - * its readability graph are: - *
{@code - * m1 --> m2 - * m1 --> java.xml - * }- * where module {@code java.xml} is in the parent configuration. For - * simplicity, this example omits the implicitly declared dependence on the - * {@code java.base} module. - * - *
Requires clauses that are "{@code requires static}" express an optional - * dependence (except at compile-time). If a module declares that it - * "{@code requires static M}" then resolution does not search the observable - * modules for "{@code M}". However, if "{@code M}" is resolved (because resolution - * resolves a module that requires "{@code M}" without the {@link - * java.lang.module.ModuleDescriptor.Requires.Modifier#STATIC static} modifier) - * then the readability graph will contain read edges for each module that - * "{@code requires static M}".
- * - *{@link java.lang.module.ModuleDescriptor#isAutomatic() Automatic} modules - * receive special treatment during resolution. Each automatic module is resolved - * as if it "{@code requires transitive}" all observable automatic modules and - * all automatic modules in the parent configurations. Each automatic module is - * resolved so that it reads all other modules in the resulting configuration and - * all modules in parent configurations.
- * - *Service binding is the process of augmenting a graph of resolved modules - * from the set of observable modules induced by the service-use dependence - * ({@code uses} and {@code provides} clauses). Any module that was not - * previously in the graph requires resolution to compute its transitive - * closure. Service binding is an iterative process in that adding a module - * that satisfies some service-use dependence may introduce new service-use - * dependences.
- * - *Suppose we have the following observable modules:
- *{@code - * module m1 { exports p; uses p.S; } - * module m2 { requires m1; provides p.S with p2.S2; } - * module m3 { requires m1; requires m4; provides p.S with p3.S3; } - * module m4 { } - * }- * - *
If the module {@code m1} is resolved then the resulting graph of modules - * has one module ({@code m1}). If the graph is augmented with modules induced - * by the service-use dependence relation then the configuration will contain - * four modules ({@code m1}, {@code m2}, {@code m3}, {@code m4}). The edges in - * its readability graph are:
- *{@code - * m2 --> m1 - * m3 --> m1 - * m3 --> m4 - * }- *
The edges in the conceptual service-use graph are:
- *{@code - * m1 --> m2 (meaning m1 uses a service that is provided by m2) - * m1 --> m3 - * }- * - *
Unless otherwise noted, passing a {@code null} argument to a constructor * or method of any class or interface in this package will cause a {@link * java.lang.NullPointerException NullPointerException} to be thrown. Additionally, * invoking a method with an array or collection containing a {@code null} element * will cause a {@code NullPointerException}, unless otherwise specified.
* + * + *Resolution is the process of computing how modules depend on each other. + * The process occurs at compile time and run time.
+ * + *Resolution is a two-step process. The first step recursively enumerates + * the 'requires' directives of a set of root modules. If all the enumerated + * modules are observable, then the second step computes their readability graph. + * The readability graph embodies how modules depend on each other, which in + * turn controls access across module boundaries.
+ * + *Recursive enumeration takes a set of module names, looks up each of their + * module declarations, and for each module declaration, recursively enumerates: + * + *
the module names given by the 'requires' directives with the + * 'transitive' modifier, and
at the discretion of the host system, the module names given by + * the 'requires' directives without the 'transitive' modifier.
Module declarations are looked up in a set of observable modules. The set + * of observable modules is determined in an implementation specific manner. The + * set of observable modules may include modules with explicit declarations + * (that is, with a {@code module-info.java} source file or {@code module-info.class} + * file) and modules with implicit declarations (that is, + * automatic modules). + * Because an automatic module has no explicit module declaration, it has no + * 'requires' directives of its own, although its name may be given by a + * 'requires' directive of an explicit module declaration.
+ + *The set of root modules, whose names are the initial input to this + * algorithm, is determined in an implementation specific manner. The set of + * root modules may include automatic modules.
+ * + *If at least one automatic module is enumerated by this algorithm, then + * every observable automatic module must be enumerated, regardless of whether + * any of their names are given by 'requires' directives of explicit module + * declarations.
+ * + *If any of the following conditions occur, then resolution fails: + *
Any root module is not observable.
Any module whose name is given by a 'requires' directive with the + * 'transitive' modifier is not observable.
At the discretion of the host system, any module whose name is given + * by a 'requires' directive without the 'transitive' modifier is not + * observable.
The algorithm in this step enumerates the same module name twice. This + * indicates a cycle in the 'requires' directives, disregarding any 'transitive' + * modifiers.
Otherwise, resolution proceeds to step 2.
+ * + *A 'requires' directive (irrespective of 'transitive') expresses that + * one module depends on some other module. The effect of the 'transitive' + * modifier is to cause additional modules to also depend on the other module. + * If module M 'requires transitive N', then not only does M depend on N, but + * any module that depends on M also depends on N. This allows M to be + * refactored so that some or all of its content can be moved to a new module N + * without breaking modules that have a 'requires M' directive.
+ * + *Module dependencies are represented by the readability graph. The + * readability graph is a directed graph whose vertices are the modules + * enumerated in step 1 and whose edges represent readability between pairs of + * modules. The edges are specified as follows: + * + *
First, readability is determined by the 'requires' directives of the + * enumerated modules, disregarding any 'transitive' modifiers: + * + *
For each enumerated module A that 'requires' B: A "reads" B.
For each enumerated module X that is automatic: X "reads" every + * other enumerated module (it is "as if" an automatic module has 'requires' + * directives for every other enumerated module).
Second, readability is augmented to account for 'transitive' modifiers: + *
For each enumerated module A that "reads" B:
+ *If B 'requires transitive' C, then A "reads" C as well as B. This + * augmentation is recursive: since A "reads" C, if C 'requires transitive' + * D, then A "reads" D as well as C and B.
If B is an automatic module, then A "reads" every other enumerated + * automatic module. (It is "as if" an automatic module has 'requires transitive' + * directives for every other enumerated automatic module).
Finally, every module "reads" itself.
+ * + *If any of the following conditions occur in the readability graph, then + * resolution fails: + *
A module "reads" two or more modules with the same name. This includes + * the case where a module "reads" another with the same name as itself.
Two or more modules export a package with the same name to a module + * that "reads" both. This includes the case where a module M containing package + * p "reads" another module that exports p to M.
A module M declares that it 'uses p.S' or 'provides p.S with ...' but + * package p is neither in module M nor exported to M by any module that M + * "reads".
Otherwise, resolution succeeds, and the result of resolution is the + * readability graph. + * + *
The set of root modules at compile-time is usually the set of modules + * being compiled. At run-time, the set of root modules is usually the + * application module specified to the 'java' launcher. When compiling code in + * the unnamed module, or at run-time when the main application class is loaded + * from the class path, then the default set of root modules is implementation + * specific (In the JDK implementation it is the module "java.se", if observable, + * and every observable module that exports an API).
+ * + *The set of observable modules at both compile-time and run-time is determined + * by searching an abstract module path. The module path is typically composed + * of search paths that are searched in order:
+ * + *At compile-time only, a compilation module path that contains module + * definitions in source form.
The upgrade module path containing compiled definitions of modules + * intended to be used in place of upgradeable modules built-in to the + * environment.
The system modules which are the compiled modules built-in to the + * environment.
The application module path which contains compiled definitions of + * library and application modules.
'requires' directives that have the 'static' modifier express an optional + * dependence at run time. If a module declares that it 'requires static M' then + * resolution does not search the observable modules for M to satisfy the dependency. + * However, if M is recursively enumerated at step 1 then all modules that are + * enumerated and `requires static M` will read M.
+ * + *Resolution may be partial at compile-time in that the complete transitive + * closure may not be required to compile a set of modules. Minimally, the + * readability graph that is constructed and validated at compile-time includes + * the modules being compiled, their direct dependences, and all implicitly + * declared dependences (requires transitive).
+ * + *At run-time, resolution is an additive process. The recursive enumeration + * at step 1 may be relative to previous resolutions so that a root module, + * or a module named in a 'requires' directive, is not enumerated when it was + * enumerated by a previous (or parent) resolution. The readability graph that + * is the result of resolution may therefore have a vertex for a module enumerated + * in step 1 but with an edge to represent that the module reads a module that + * was enumerated by previous (or parent) resolution.
+ * * @since 9 * @spec JPMS */ diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java index 35c689d56cc..f725eb35e6a 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java @@ -304,7 +304,7 @@ public class AccessibleObject implements AnnotatedElement { if (isClassPublic && declaringModule.isExported(pn, callerModule)) { // member is public if (Modifier.isPublic(modifiers)) { - logIfExportedByBackdoor(caller, declaringClass); + logIfExportedForIllegalAccess(caller, declaringClass); return true; } @@ -312,14 +312,14 @@ public class AccessibleObject implements AnnotatedElement { if (Modifier.isProtected(modifiers) && Modifier.isStatic(modifiers) && isSubclassOf(caller, declaringClass)) { - logIfExportedByBackdoor(caller, declaringClass); + logIfExportedForIllegalAccess(caller, declaringClass); return true; } } // package is open to caller if (declaringModule.isOpen(pn, callerModule)) { - logIfOpenedByBackdoor(caller, declaringClass); + logIfOpenedForIllegalAccess(caller, declaringClass); return true; } @@ -353,26 +353,26 @@ public class AccessibleObject implements AnnotatedElement { return false; } - private void logIfOpenedByBackdoor(Class> caller, Class> declaringClass) { + private void logIfOpenedForIllegalAccess(Class> caller, Class> declaringClass) { Module callerModule = caller.getModule(); Module targetModule = declaringClass.getModule(); // callerModule is null during early startup if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) { IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger(); if (logger != null) { - logger.logIfOpenedByBackdoor(caller, declaringClass, this::toShortString); + logger.logIfOpenedForIllegalAccess(caller, declaringClass, this::toShortString); } } } - private void logIfExportedByBackdoor(Class> caller, Class> declaringClass) { + private void logIfExportedForIllegalAccess(Class> caller, Class> declaringClass) { Module callerModule = caller.getModule(); Module targetModule = declaringClass.getModule(); // callerModule is null during early startup if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) { IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger(); if (logger != null) { - logger.logIfExportedByBackdoor(caller, declaringClass, this::toShortString); + logger.logIfExportedForIllegalAccess(caller, declaringClass, this::toShortString); } } } @@ -634,7 +634,7 @@ public class AccessibleObject implements AnnotatedElement { } // access okay - logIfExportedByBackdoor(caller, memberClass); + logIfExportedForIllegalAccess(caller, memberClass); // Success: Update the cache. Object cache = (targetClass != null diff --git a/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java b/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java index 42db72d2d48..2852384eb4b 100644 --- a/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java +++ b/jdk/src/java.base/share/classes/java/util/ServiceConfigurationError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -27,33 +27,12 @@ package java.util; /** - * Error thrown when something goes wrong while loading a service provider. - * - *This error will be thrown in the following situations: - * - *
Providers deployed as explicit modules on the module path are - * instantiated by a provider factory or directly via the provider's - * constructor. In the module declaration then the class name specified in the - * provides clause is a provider factory if it is public and defines a - * public static no-args method named "{@code provider}". The return type of - * the method must be assignable to the service type. If the class is - * not a provider factory then it is public with a public zero-argument - * constructor. The requirement that the provider factory or provider class - * be public helps to document the intent that the provider will be - * instantiated by the service-provider loading facility. + *
A service loader is created by invoking one of the static {@code load} + * methods that {@code ServiceLoader} defines. The resulting service loader + * can be used to locate and instantiate service provider implementations by + * means of its {@link #iterator() iterator} ({@code ServiceLoader} implements + * {@code Iterable}) or by consuming elements from its {@link #stream() stream}. + * + *
As an example, suppose the service type is {@code com.example.CodecSet} + * and it defines two abstract methods to obtain encoders and decoders: + *
{@code + * package com.example; + * public interface CodecSet { + * Encoder getEncoder(String encodingName); + * Decoder getDecoder(String encodingName); + * } + * }+ * With this example, the following uses the service loader's iterator to find + * a provider that supports a specific encoding: + *
{@code + * public Encoder getEncoder(String encodingName) { + * ServiceLoader+ * + *loader = ServiceLoader.load(CodeSet.class); + * for (CodecSet cs : loader) { + * Encoder encoder = cs.getEncoder(encodingName); + * if (encoder != null) + * return encoder; + * } + * return null; + * } + * }
Selecting a provider or filtering providers will usually involve invoking + * a provider method. In the {@code CodeSet} example, the {@code getEncoder} + * method is used to select the implementation. Where selection or filtering based + * on the provider class is needed then it can be done when consuming the elements + * of the service loader's stream. As an example, the following collects the + * {@code CodeSet} implementations that have a specific annotation: + *
{@code + * Set+ * + *providers = ServiceLoader.load(CodecSet.class) + * .stream() + * .filter(p -> p.type().isAnnotationPresent(Managed.class)) + * .map(Provider::get) + * .collect(Collectors.toSet()); + * }
Providers are located and instantiated lazily, that is, on demand. A + * service loader maintains a cache of the providers that have been loaded so + * far. Each invocation of the {@code iterator} method returns an iterator that + * first yields all of the elements cached from previous iteration, in + * instantiation order, and then lazily locates and instantiates any remaining + * providers, adding each one to the cache in turn. Similarly, each invocation + * of the {@code stream} method returns a stream that first processes all + * providers loaded by previous stream operations, in load order, and then lazily + * locates any remaining providers. Caches are cleared via the {@link #reload + * reload} method. + * + *
A provider deployed as an explicit module must have an appropriate + * provides clause in its module descriptor to declare that the module + * provides an implementation of the service. + * + *
A provider deployed as an explicit module is instantiated by a + * provider factory or directly via the provider's constructor. In the + * module declaration then the class name specified in the provides clause + * is a provider factory if it is public and explicitly declares a public static + * no-args method named "{@code provider}". The return type of the method must be + * assignable to the service type. If the class is not a provider factory + * then it is public with a public zero-argument constructor. The requirement + * that the provider factory or provider class be public helps to document the + * intent that the provider will be instantiated by the service-provider loading + * facility. + * + *
Providers deployed as {@link + * java.lang.module.ModuleDescriptor#isAutomatic automatic-modules} on the + * module path must have a public zero-argument constructor. If the provider + * also declares a public static method named "{@code provider}" then it is + * ignored. * *
As an example, suppose a module declares the following: * @@ -99,38 +165,33 @@ import jdk.internal.reflect.Reflection; * provides com.example.CodecSet with com.example.impl.ExtendedCodecsFactory; * } * - *
where {@code com.example.CodecSet} is the service type, {@code - * com.example.impl.StandardCodecs} is a provider class that is public with a - * public no-args constructor, {@code com.example.impl.ExtendedCodecsFactory} - * is a public class that defines a public static no-args method named - * "{@code provider}" with a return type that is {@code CodecSet} or a subtype - * of. For this example then {@code StandardCodecs}'s no-arg constructor will + * where + *
For this example then {@code StandardCodecs}'s no-arg constructor will * be used to instantiate {@code StandardCodecs}. {@code ExtendedCodecsFactory} * will be treated as a provider factory and {@code * ExtendedCodecsFactory.provider()} will be invoked to obtain the provider. * - *
Providers deployed on the class path or as {@link - * java.lang.module.ModuleDescriptor#isAutomatic automatic-modules} on the - * module path must have a public zero-argument constructor. + *
An application or library using this loading facility and developed - * and deployed as an explicit module must have an appropriate uses - * clause in its module descriptor to declare that the module uses - * implementations of the service. A corresponding requirement is that a - * provider deployed as an explicit module must have an appropriate - * provides clause in its module descriptor to declare that the module - * provides an implementation of the service. The uses and - * provides allow consumers of a service to be linked to modules - * containing providers of the service. - * - *
A service provider that is packaged as a JAR file for the class path is
- * identified by placing a provider-configuration file in the resource
- * directory {@code META-INF/services}. The file's name is the fully-qualified
- * binary name of the service's
- * type. The file contains a list of fully-qualified binary names of concrete
- * provider classes, one per line. Space and tab characters surrounding each
- * name, as well as blank lines, are ignored. The comment character is
- * {@code '#'} ('\u0023'
,
+ *
A service provider that is packaged as a JAR file for
+ * the class path is identified by placing a provider-configuration file
+ * in the resource directory {@code META-INF/services}. The file's name is
+ * the fully-qualified binary name
+ * of the service's type. The file contains a list of fully-qualified binary
+ * names of concrete provider classes, one per line. Space and tab characters
+ * surrounding each name, as well as blank lines, are ignored. The comment
+ * character is {@code '#'} ('\u0023'
,
* NUMBER SIGN); on
* each line all characters following the first comment character are ignored.
* The file must be encoded in UTF-8.
@@ -141,103 +202,88 @@ import jdk.internal.reflect.Reflection;
* unit as the provider itself. The provider must be visible from the same
* class loader that was initially queried to locate the configuration file;
* note that this is not necessarily the class loader from which the file was
- * actually loaded.
+ * actually located.
*
- *
Providers are located and instantiated lazily, that is, on demand. A - * service loader maintains a cache of the providers that have been loaded so - * far. Each invocation of the {@link #iterator iterator} method returns an - * iterator that first yields all of the elements cached from previous - * iteration, in instantiation order, and then lazily locates and instantiates - * any remaining providers, adding each one to the cache in turn. Similarly, - * each invocation of the {@link #stream stream} method returns a stream that - * first processes all providers loaded by previous stream operations, in load - * order, and then lazily locates any remaining providers. Caches are cleared - * via the {@link #reload reload} method. + *
For the example, then suppose {@code com.example.impl.StandardCodecs} is + * packaged in a JAR file for the class path then the JAR file will contain a + * file named: + *
{@code + * META-INF/services/com.example.CodecSet + * }+ * that contains the line: + *
{@code + * com.example.impl.StandardCodecs # Standard codecs + * }* - *
The {@code load} methods locate providers using a class loader or module - * {@link ModuleLayer layer}. When locating providers using a class loader then - * providers in both named and unnamed modules may be located. When locating - * providers using a module layer then only providers in named modules in - * the layer (or parent layers) are located. + *
An application or library using this loading facility and developed + * and deployed as an explicit module must have an appropriate uses + * clause in its module descriptor to declare that the module uses + * implementations of the service. Combined with the requirement is that a + * provider deployed as an explicit module must have an appropriate + * provides clause allows consumers of a service to be linked + * to modules containing providers of the service. * - *
When locating providers using a class loader then any providers in named - * modules defined to the class loader, or any class loader that is reachable - * via parent delegation, are located. Additionally, providers in module layers - * other than the {@link ModuleLayer#boot() boot} layer, where the module layer - * contains modules defined to the class loader, or any class loader reachable - * via parent delegation, are also located. For example, suppose there is a - * module layer where each module is defined to its own class loader (see {@link - * ModuleLayer#defineModulesWithManyLoaders defineModulesWithManyLoaders}). If the - * {@code load} method is invoked to locate providers using any of these class - * loaders for this layer then it will locate all of the providers in that - * layer, irrespective of their defining class loader. + *
For the example, if code in a module uses a service loader to load + * implementations of {@code com.example.CodecSet} then its module will declare + * the usage with:
{@code uses com.example.CodecSet; }* - *
In the case of unnamed modules then the service configuration files are - * located using the class loader's {@link ClassLoader#getResources(String) - * ClassLoader.getResources(String)} method. Any providers listed should be - * visible via the class loader specified to the {@code load} method. If a - * provider in a named module is listed then it is ignored - this is to avoid - * duplicates that would otherwise arise when a module has both a - * provides clause and a service configuration file in {@code - * META-INF/services} that lists the same provider. + *
When using the service loader's {@code iterator} then its {@link + * Iterator#hasNext() hasNext} and {@link Iterator#next() next} methods will + * fail with {@link ServiceConfigurationError} if an error occurs locating or + * instantiating a provider. When processing the service loader's stream then + * {@code ServiceConfigurationError} is thrown by whatever method causes a + * provider class to be loaded. + * + *
When loading or instantiating a provider class in a named module then + * {@code ServiceConfigurationError} can be thrown for the following reasons:
* - *Service loaders created to locate providers using a {@code ClassLoader} - * locate providers as follows: *
Service loaders created to locate providers in a {@linkplain ModuleLayer - * module layer} will first locate providers in the layer, before locating - * providers in parent layers. Traversal of parent layers is depth-first with - * each layer visited at most once. For example, suppose L0 is the boot layer, - * L1 and L2 are custom layers with L0 as their parent. Now suppose that L3 is - * created with L1 and L2 as the parents (in that order). Using a service - * loader to locate providers with L3 as the content will locate providers - * in the following order: L3, L1, L0, L2. The ordering of modules in a layer - * is not defined. + *
When reading a provider-configuration file, or loading or instantiating a + * provider class named in a provider-configuration file, then {@code + * ServiceConfigurationError} can be thrown for the following reasons: * - *
Selecting a provider or filtering providers will usually involve invoking - * a provider method. Where selection or filtering based on the provider class is - * needed then it can be done using a {@link #stream() stream}. For example, the - * following collects the providers that have a specific annotation: - *
{@code - * Set+ *providers = ServiceLoader.load(CodecSet.class) - * .stream() - * .filter(p -> p.type().isAnnotationPresent(Managed.class)) - * .map(Provider::get) - * .collect(Collectors.toSet()); - * }
Service loaders always execute in the security context of the caller * of the iterator or stream methods and may also be restricted by the security @@ -246,91 +292,16 @@ import jdk.internal.reflect.Reflection; * the methods of the iterators which they return, from within a privileged * security context. * - *
Instances of this class are not safe for use by multiple concurrent * threads. * - *
Unless otherwise specified, passing a {@code null} argument to any * method in this class will cause a {@link NullPointerException} to be thrown. * - *
Suppose we have a service type {@code com.example.CodecSet} which is - * intended to represent sets of encoder/decoder pairs for some protocol. In - * this case it is an abstract class with two abstract methods: - * - *
- * - * Each method returns an appropriate object or {@code null} if the provider - * does not support the given encoding. Typical providers support more than - * one encoding. - * - *- * public abstract Encoder getEncoder(String encodingName); - * public abstract Decoder getDecoder(String encodingName);
The {@code CodecSet} class creates and saves a single service instance - * at initialization: - * - *
{@code - * private static ServiceLoader- * - *codecSetLoader - * = ServiceLoader.load(CodecSet.class); - * }
To locate an encoder for a given encoding name it defines a static - * factory method which iterates through the known and available providers, - * returning only when it has located a suitable encoder or has run out of - * providers. - * - *
{@code - * public static Encoder getEncoder(String encodingName) { - * for (CodecSet cp : codecSetLoader) { - * Encoder enc = cp.getEncoder(encodingName); - * if (enc != null) - * return enc; - * } - * return null; - * }}- * - *
A {@code getDecoder} method is defined similarly. - * - *
If the code creating and using the service loader is developed as - * a module then its module descriptor will declare the usage with: - *
{@code uses com.example.CodecSet;}- * - *
Now suppose that {@code com.example.impl.StandardCodecs} is an - * implementation of the {@code CodecSet} service and developed as a module. - * In that case then the module with the service provider module will declare - * this in its module descriptor: - *
{@code provides com.example.CodecSet with com.example.impl.StandardCodecs; - * }- * - *
On the other hand, suppose {@code com.example.impl.StandardCodecs} is - * packaged in a JAR file for the class path then the JAR file will contain a - * file named: - *
{@code META-INF/services/com.example.CodecSet}- * that contains the single line: - *
{@code com.example.impl.StandardCodecs # Standard codecs}- * - *
Usage Note If - * the class path of a class loader that is used for provider loading includes - * remote network URLs then those URLs will be dereferenced in the process of - * searching for provider-configuration files. - * - *
This activity is normal, although it may cause puzzling entries to be - * created in web-server logs. If a web server is not configured correctly, - * however, then this activity may cause the provider-loading algorithm to fail - * spuriously. - * - *
A web server should return an HTTP 404 (Not Found) response when a
- * requested resource does not exist. Sometimes, however, web servers are
- * erroneously configured to return an HTTP 200 (OK) response along with a
- * helpful HTML error page in such cases. This will cause a {@link
- * ServiceConfigurationError} to be thrown when this class attempts to parse
- * the HTML page as a provider-configuration file. The best solution to this
- * problem is to fix the misconfigured web server to return the correct
- * response code (HTTP 404) along with the HTML error page.
- *
* @param Service providers are located in named modules defined to the
+ * class loader, or any class loader that is reachable via parent
+ * delegation. Additionally, and with the exception of the bootstrap and {@linkplain
+ * ClassLoader#getPlatformClassLoader() platform} class loaders, if the
+ * class loader, or any class loader reachable via parent delegation,
+ * defines modules in a module layer then the providers in the module layer
+ * are located. For example, suppose there is a module layer where each
+ * module is defined to its own class loader (see {@link
+ * ModuleLayer#defineModulesWithManyLoaders defineModulesWithManyLoaders}).
+ * If this {@code ServiceLoader.load} method is invoked to locate providers
+ * using any of the class loaders created for this layer then it will locate
+ * all of the providers in that layer, irrespective of their defining class
+ * loader. A provider is an unnamed modules is located if its class
+ * name is listed in a service configuration file located by the the class
+ * loader's {@link ClassLoader#getResources(String) getResources} method.
+ * The provider class must be visible to the class loader. If a provider
+ * class is in a named module is listed then it is ignored (this is to
+ * avoid duplicates that would otherwise arise when a module has both a
+ * provides clause and a service configuration file in {@code
+ * META-INF/services} that lists the same provider). The ordering that the service loader's iterator and stream locate
+ * providers and yield elements is as follows:
+ *
+ * Providers in named modules are located before service
+ * providers in unnamed modules. When locating providers in named modules then the service
+ * loader will first locate any service providers in modules defined to
+ * the class loader, then its parent class loader, its parent parent,
+ * and so on to the bootstrap class loader. If a class loader or any
+ * class loader in the parent delegation chain, defines modules in a
+ * module layer then all providers in that layer are located
+ * (irrespective of their class loader) before providers in the parent
+ * class loader are located. The ordering of modules defined to the
+ * same class loader, or the ordering of modules in a layer, is not
+ * defined. If a named module declares more than one provider then the
+ * providers are located in the order that its module descriptor
+ * {@linkplain java.lang.module.ModuleDescriptor.Provides#providers()
+ * lists the providers}. Providers added dynamically by instrumentation
+ * agents (see {@link java.lang.instrument.Instrumentation#redefineModule
+ * redefineModule}) are always located after providers declared by the
+ * module. When locating providers in unnamed modules then the
+ * ordering is based on the order that the class loader's {@link
+ * ClassLoader#getResources(String) getResources} method finds the
+ * service configuration files and within that, the order that the class
+ * names are listed in the file. This activity is normal, although it may cause puzzling entries to be
+ * created in web-server logs. If a web server is not configured correctly,
+ * however, then this activity may cause the provider-loading algorithm to fail
+ * spuriously.
+ *
+ * A web server should return an HTTP 404 (Not Found) response when a
+ * requested resource does not exist. Sometimes, however, web servers are
+ * erroneously configured to return an HTTP 200 (OK) response along with a
+ * helpful HTML error page in such cases. This will cause a {@link
+ * ServiceConfigurationError} to be thrown when this class attempts to parse
+ * the HTML page as a provider-configuration file. The best solution to this
+ * problem is to fix the misconfigured web server to return the correct
+ * response code (HTTP 404) along with the HTML error page.
*
* @param An invocation of this convenience method of the form
* This convenience method is equivalent to: This method is intended for use when only installed providers are
@@ -1532,9 +1655,30 @@ public final class ServiceLoader The ordering that the service loader's iterator and stream locate
+ * providers and yield elements is as follows:
+ *
+ * Providers are located in a module layer before locating providers
+ * in parent layers. Traversal of parent layers is depth-first with each
+ * layer visited at most once. For example, suppose L0 is the boot layer, L1
+ * and L2 are modules layers with L0 as their parent. Now suppose that L3 is
+ * created with L1 and L2 as the parents (in that order). Using a service
+ * loader to locate providers with L3 as the context will locate providers
+ * in the following order: L3, L1, L0, L2. If a named module declares more than one provider then the
+ * providers are located in the order that its module descriptor
+ * {@linkplain java.lang.module.ModuleDescriptor.Provides#providers()
+ * lists the providers}. Providers added dynamically by instrumentation
+ * agents are always located after providers declared by the module. The ordering of modules in a module layer is not defined. An agent is deployed as a JAR file. An attribute in the JAR file manifest
+ * specifies the agent class which will be loaded to start the agent. Agents can
+ * be started in several ways:
+ *
+ * For implementations that support a command-line interface, an agent
+ * can be started by specifying an option on the command-line. An implementation may support a mechanism to start agents some time
+ * after the VM has started. For example, an implementation may provide a
+ * mechanism that allows a tool to attach to a running application, and
+ * initiate the loading of the tool's agent into the running application. An agent may be packaged with an application in an executable JAR
+ * file. Each of these ways to start an agent is described below.
+ *
+ *
+ * Where an implementation provides a means to start agents from the
+ * command-line interface, an agent is started by adding the following option
+ * to the command-line:
+ *
+ * The manifest of the agent JAR file must contain the attribute {@code
+ * Premain-Class} in its main manifest. The value of this attribute is the
+ * name of the agent class. The agent class must implement a public
+ * static {@code premain} method similar in principle to the {@code main}
+ * application entry point. After the Java Virtual Machine (JVM) has
+ * initialized, the {@code premain} method will be called, then the real
+ * application {@code main} method. The {@code premain} method must return
+ * in order for the startup to proceed.
+ *
+ * The {@code premain} method has one of two possible signatures. The
+ * JVM first attempts to invoke the following method on the agent class:
+ *
+ * If the agent class does not implement this method then the JVM will
+ * attempt to invoke:
+ * The agent class may also have an {@code agentmain} method for use when
+ * the agent is started after VM startup (see below). When the agent is started
+ * using a command-line option, the {@code agentmain} method is not invoked.
+ *
+ * Each agent is passed its agent options via the {@code agentArgs} parameter.
+ * The agent options are passed as a single string, any additional parsing
+ * should be performed by the agent itself.
+ *
+ * If the agent cannot be started (for example, because the agent class
+ * cannot be loaded, or because the agent class does not have an appropriate
+ * {@code premain} method), the JVM will abort. If a {@code premain} method
+ * throws an uncaught exception, the JVM will abort.
+ *
+ * An implementation is not required to provide a way to start agents
+ * from the command-line interface. When it does, then it supports the
+ * {@code -javaagent} option as specified above. The {@code -javaagent} option
+ * may be used multiple times on the same command-line, thus starting multiple
+ * agents. The {@code premain} methods will be called in the order that the
+ * agents are specified on the command line. More than one agent may use the
+ * same {@code There are no modeling restrictions on what the agent {@code premain}
+ * method may do. Anything application {@code main} can do, including creating
+ * threads, is legal from {@code premain}.
+ *
+ *
+ * An implementation may provide a mechanism to start agents sometime after
+ * the the VM has started. The details as to how this is initiated are
+ * implementation specific but typically the application has already started and
+ * its {@code main} method has already been invoked. In cases where an
+ * implementation supports the starting of agents after the VM has started the
+ * following applies:
+ *
+ * The manifest of the agent JAR must contain the attribute {@code
+ * Agent-Class} in its main manfiest. The value of this attribute is the name
+ * of the agent class. The agent class must implement a public static {@code agentmain}
+ * method. The {@code agentmain} method has one of two possible signatures. The JVM
+ * first attempts to invoke the following method on the agent class:
+ *
+ * If the agent class does not implement this method then the JVM will
+ * attempt to invoke:
+ *
+ * The agent class may also have a {@code premain} method for use when the
+ * agent is started using a command-line option. When the agent is started after
+ * VM startup the {@code premain} method is not invoked.
+ *
+ * The agent is passed its agent options via the {@code agentArgs}
+ * parameter. The agent options are passed as a single string, any additional
+ * parsing should be performed by the agent itself.
+ *
+ * The {@code agentmain} method should do any necessary initialization
+ * required to start the agent. When startup is complete the method should
+ * return. If the agent cannot be started (for example, because the agent class
+ * cannot be loaded, or because the agent class does not have a conformant
+ * {@code agentmain} method), the JVM will not abort. If the {@code agentmain}
+ * method throws an uncaught exception it will be ignored (but may be logged
+ * by the JVM for troubleshooting purposes).
+ *
+ *
+ * The JAR File Specification defines manifest attributes for standalone
+ * applications that are packaged as executable JAR files. If an
+ * implementation supports a mechanism to start an application as an executable
+ * JAR then the main manifest may include the {@code Launcher-Agent-Class}
+ * attribute to specify the class name of an agent to start before the application
+ * {@code main} method is invoked. The Java virtual machine attempts to
+ * invoke the following method on the agent class:
+ *
+ * If the agent class does not implement this method then the JVM will
+ * attempt to invoke:
+ *
+ * The value of the {@code agentArgs} parameter is always the empty string.
+ *
+ * The {@code agentmain} method should do any necessary initialization
+ * required to start the agent and return. If the agent cannot be started, for
+ * example the agent class cannot be loaded, the agent class does not define a
+ * conformant {@code agentmain} method, or the {@code agentmain} method throws
+ * an uncaught exception or error, the JVM will abort.
+ *
+ *
+ * Classes loaded from the agent JAR file are loaded by the
+ * {@linkplain ClassLoader#getSystemClassLoader() system class loader} and are
+ * members of the system class loader's {@linkplain ClassLoader#getUnnamedModule()
+ * unnamed module}. The system class loader typically defines the class containing
+ * the application {@code main} method too.
+ *
+ * The classes visible to the agent class are the classes visible to the system
+ * class loader and minimally include:
+ *
+ * The classes in packages exported by the modules in the {@linkplain
+ * ModuleLayer#boot() boot layer}. Whether the boot layer contains all platform
+ * modules or not will depend on the initial module or how the application was
+ * started. The classes that can be defined by the system class loader (typically
+ * the class path) to be members of its unnamed module. Any classes that the agent arranges to be defined by the bootstrap
+ * class loader to be members of its unnamed module. If agent classes need to link to classes in platform (or other) modules
+ * that are not in the boot layer then the application may need to be started in
+ * a way that ensures that these modules are in the boot layer. In the JDK
+ * implementation for example, the {@code --add-modules} command line option can
+ * be used to add modules to the set of root modules to resolve at startup. Supporting classes that the agent arranges to be loaded by the bootstrap
+ * class loader (by means of {@link Instrumentation#appendToBootstrapClassLoaderSearch
+ * appendToBootstrapClassLoaderSearch} or the {@code Boot-Class-Path} attribute
+ * specified below), must link only to classes defined to the bootstrap class loader.
+ * There is no guarantee that all platform classes can be defined by the boot
+ * class loader.
+ *
+ * If a custom system class loader is configured (by means of the system property
+ * {@code java.system.class.loader} as specified in the {@link
+ * ClassLoader#getSystemClassLoader() getSystemClassLoader} method) then it must
+ * define the {@code appendToClassPathForInstrumentation} method as specified in
+ * {@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}.
+ * In other words, a custom system class loader must support the mechanism to
+ * add an agent JAR file to the system class loader search.
+ *
+ * The following manifest attributes are defined for an agent JAR file:
+ *
+ * An agent JAR file may have both the {@code Premain-Class} and {@code
+ * Agent-Class} attributes present in the manifest. When the agent is started
+ * on the command-line using the {@code -javaagent} option then the {@code
+ * Premain-Class} attribute specifies the name of the agent class and the {@code
+ * Agent-Class} attribute is ignored. Similarly, if the agent is started sometime
+ * after the VM has started, then the {@code Agent-Class} attribute specifies
+ * the name of the agent class (the value of {@code Premain-Class} attribute is
+ * ignored).
+ *
+ *
+ * As an aid to agents that deploy supporting classes on the search path of
+ * the bootstrap class loader, or the search path of the class loader that loads
+ * the main agent class, the Java virtual machine arranges for the module of
+ * transformed classes to read the unnamed module of both class loaders.
+ *
+ * @since 1.5
+ * @revised 1.6
+ * @revised 9
+ */
+
+package java.lang.instrument;
\ No newline at end of file
diff --git a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html b/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html
deleted file mode 100644
index 5c40a234c91..00000000000
--- a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html
+++ /dev/null
@@ -1,356 +0,0 @@
-
-
-
-
-
-An agent is deployed as a JAR file. An attribute in the JAR file manifest specifies the
-agent class which will be loaded to start the agent. For implementations that support a command-line
-interface, an agent is started by specifying an option on the command-line.
-Implementations may also support a mechanism to start agents some time after the VM has
-started. For example, an implementation may provide a mechanism that allows a tool to
-attach to a running application, and initiate the loading of the tool's agent into
-the running application. The details as to how the load is initiated, is implementation
-dependent.
-
-
-An implementation is not required to provide a way to start agents from the
-command-line interface. On implementations that do provide a way to start agents
-from the command-line interface, an agent is started by adding this option to
-the command-line:
-
-The manifest of the agent JAR file must contain the attribute
-The
-If the agent class does not implement this method then the JVM will attempt to invoke:
-
-
-The agent class may also have an
-The agent class will be loaded by the system class loader
-(see {@link java.lang.ClassLoader#getSystemClassLoader ClassLoader.getSystemClassLoader}). This is
-the class loader which typically loads the class containing the application
-Each agent is passed its agent options via the
-If the agent cannot be resolved
-(for example, because the agent class cannot be loaded,
-or because the agent class does not have an appropriate
-An implementation may provide a mechanism to start agents sometime after the
-the VM has started. The details as to how this is initiated are implementation
-specific but typically the application has already started and its The manifest of the agent JAR must contain the attribute The agent class must implement a public static The system class loader (
- {@link java.lang.ClassLoader#getSystemClassLoader ClassLoader.getSystemClassLoader}) must
- support a mechanism to add an agent JAR file to the system class path.
- If it is a custom system class loader then it must define the
-
-The agent JAR is appended to the system class path. This is the class loader that typically loads
-the class containing the application
-If the agent class does not implement this method then the JVM will attempt to invoke:
-
-
-The agent class may also have an
-The agent is passed its agent options via the
-The
-If the agent class does not implement this method then the JVM will attempt to invoke:
-
-
-The value of the
-The
-Supporting classes that the agent makes visible to the bootstrap class loader
-(by means of {@link Instrumentation#appendToBootstrapClassLoaderSearch
-appendToBootstrapClassLoaderSearch} or the
-An agent JAR file may have both the
* The type of the service to be loaded by this loader
*
@@ -548,32 +519,83 @@ public final class ServiceLoader
}
/**
- * Uses Class.forName to load a provider class in a module.
- *
- * @throws ServiceConfigurationError
- * If the class cannot be loaded
+ * Returns {@code true} if the provider is in an explicit module
*/
- private Class> loadProviderInModule(Module module, String cn) {
- Class> clazz = null;
- if (acc == null) {
- try {
- clazz = Class.forName(module, cn);
- } catch (LinkageError e) {
- fail(service, "Unable to load " + cn, e);
- }
- } else {
- PrivilegedExceptionAction
* permissions, the static factory to obtain the provider or the
* provider's no-arg constructor.
*/
- private final static class ProviderImpl implements Provider {
+ private static class ProviderImpl implements Provider {
final Class service;
+ final Class extends S> type;
+ final Method factoryMethod; // factory method or null
+ final Constructor extends S> ctor; // public no-args constructor or null
final AccessControlContext acc;
- final Method factoryMethod; // factory method or null
- final Class extends S> type;
- final Constructor extends S> ctor; // public no-args constructor or null
-
- /**
- * Creates a Provider.
- *
- * @param service
- * The service type
- * @param clazz
- * The provider (or provider factory) class
- * @param acc
- * The access control context when running with security manager
- *
- * @throws ServiceConfigurationError
- * If the class is not public; If the class defines a public
- * static provider() method with a return type that is assignable
- * to the service type or the class is not a provider class with
- * a public no-args constructor.
- */
- @SuppressWarnings("unchecked")
- ProviderImpl(Class> service, Class> clazz, AccessControlContext acc) {
- this.service = (Class) service;
- this.acc = acc;
-
- int mods = clazz.getModifiers();
- if (!Modifier.isPublic(mods)) {
- fail(service, clazz + " is not public");
- }
-
- // if the class is in an explicit module then see if it is
- // a provider factory class
- Method factoryMethod = null;
- if (inExplicitModule(clazz)) {
- factoryMethod = findStaticProviderMethod(clazz);
- if (factoryMethod != null) {
- Class> returnType = factoryMethod.getReturnType();
- if (!service.isAssignableFrom(returnType)) {
- fail(service, factoryMethod + " return type not a subtype");
- }
- }
- }
+ ProviderImpl(Class service,
+ Class extends S> type,
+ Method factoryMethod,
+ AccessControlContext acc) {
+ this.service = service;
+ this.type = type;
this.factoryMethod = factoryMethod;
+ this.ctor = null;
+ this.acc = acc;
+ }
- if (factoryMethod == null) {
- // no factory method so must have a public no-args constructor
- if (!service.isAssignableFrom(clazz)) {
- fail(service, clazz.getName() + " not a subtype");
- }
- this.type = (Class extends S>) clazz;
- this.ctor = (Constructor extends S>) getConstructor(clazz);
- } else {
- this.type = (Class extends S>) factoryMethod.getReturnType();
- this.ctor = null;
- }
+ ProviderImpl(Class service,
+ Class extends S> type,
+ Constructor extends S> ctor,
+ AccessControlContext acc) {
+ this.service = service;
+ this.type = type;
+ this.factoryMethod = null;
+ this.ctor = ctor;
+ this.acc = acc;
}
@Override
@@ -656,72 +646,6 @@ public final class ServiceLoader
}
}
- /**
- * Returns {@code true} if the provider is in an explicit module
- */
- private boolean inExplicitModule(Class> clazz) {
- Module module = clazz.getModule();
- return module.isNamed() && !module.getDescriptor().isAutomatic();
- }
-
- /**
- * Returns the public static provider method if found.
- *
- * @throws ServiceConfigurationError if there is an error finding the
- * provider method
- */
- private Method findStaticProviderMethod(Class> clazz) {
- Method method = null;
- try {
- method = LANG_ACCESS.getMethodOrNull(clazz, "provider");
- } catch (Throwable x) {
- fail(service, "Unable to get public provider() method", x);
- }
- if (method != null) {
- int mods = method.getModifiers();
- if (Modifier.isStatic(mods)) {
- assert Modifier.isPublic(mods);
- Method m = method;
- PrivilegedAction
@Override
public int hashCode() {
- return Objects.hash(type, acc);
+ return Objects.hash(service, type, acc);
}
@Override
@@ -817,11 +741,83 @@ public final class ServiceLoader
return false;
@SuppressWarnings("unchecked")
ProviderImpl> that = (ProviderImpl>)ob;
- return this.type == that.type
+ return this.service == that.service
+ && this.type == that.type
&& Objects.equals(this.acc, that.acc);
}
}
+ /**
+ * Loads a service provider in a module.
+ *
+ * Returns {@code null} if the service provider's module doesn't read
+ * the module with the service type.
+ *
+ * @throws ServiceConfigurationError if the class cannot be loaded or
+ * isn't the expected sub-type (or doesn't define a provider
+ * factory method that returns the expected type)
+ */
+ private Provider loadProvider(ServiceProvider provider) {
+ Module module = provider.module();
+ if (!module.canRead(service.getModule())) {
+ // module does not read the module with the service type
+ return null;
+ }
+
+ String cn = provider.providerName();
+ Class> clazz = null;
+ if (acc == null) {
+ try {
+ clazz = Class.forName(module, cn);
+ } catch (LinkageError e) {
+ fail(service, "Unable to load " + cn, e);
+ }
+ } else {
+ PrivilegedExceptionAction(service, type, factoryMethod, acc);
+ }
+ }
+
+ // no factory method so must be a subtype
+ if (!service.isAssignableFrom(clazz)) {
+ fail(service, clazz.getName() + " not a subtype");
+ }
+
+ @SuppressWarnings("unchecked")
+ Class extends S> type = (Class extends S>) clazz;
+ @SuppressWarnings("unchecked")
+ Constructor extends S> ctor = (Constructor extends S> ) getConstructor(clazz);
+ return new ProviderImpl(service, type, ctor, acc);
+ }
+
/**
* Implements lazy service provider lookup of service providers that
* are provided by modules in a module layer (or parent layers)
@@ -832,7 +828,9 @@ public final class ServiceLoader
Deque
@Override
public boolean hasNext() {
- // already have the next provider cached
- if (next != null)
- return true;
+ while (nextProvider == null && nextError == null) {
+ // get next provider to load
+ while (iterator == null || !iterator.hasNext()) {
+ // next layer (DFS order)
+ if (stack.isEmpty())
+ return false;
- while (true) {
-
- // next provider (or provider factory)
- if (iterator != null && iterator.hasNext()) {
- next = iterator.next();
- return true;
- }
-
- // next layer (DFS order)
- if (stack.isEmpty())
- return false;
-
- ModuleLayer layer = stack.pop();
- List
if (!hasNext())
throw new NoSuchElementException();
- // take next provider
- ServiceProvider provider = next;
- next = null;
-
- // attempt to load provider
- Module module = provider.module();
- String cn = provider.providerName();
- Class> clazz = loadProviderInModule(module, cn);
- return new ProviderImpl
{
ClassLoader currentLoader;
Iterator
return catalog.findServices(serviceName);
}
+ /**
+ * Returns the class loader that a module is defined to
+ */
+ private ClassLoader loaderFor(Module module) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ return module.getClassLoader();
+ } else {
+ PrivilegedAction
providers = catalog.findServices(serviceName);
}
- // modules in custom layers that define modules to the class loader
- if (loader == null) {
+ // modules in layers that define modules to the class loader
+ ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
+ if (loader == null || loader == platformClassLoader) {
return providers.iterator();
} else {
List
@Override
public boolean hasNext() {
- // already have the next provider cached
- if (next != null)
- return true;
-
- while (true) {
- if (iterator.hasNext()) {
- next = iterator.next();
- return true;
+ while (nextProvider == null && nextError == null) {
+ // get next provider to load
+ while (!iterator.hasNext()) {
+ if (currentLoader == null) {
+ return false;
+ } else {
+ currentLoader = currentLoader.getParent();
+ iterator = iteratorFor(currentLoader);
+ }
}
- // move to the next class loader if possible
- if (currentLoader == null) {
- return false;
- } else {
- currentLoader = currentLoader.getParent();
- iterator = iteratorFor(currentLoader);
+ // attempt to load provider
+ ServiceProvider provider = iterator.next();
+ try {
+ @SuppressWarnings("unchecked")
+ Provider
if (!hasNext())
throw new NoSuchElementException();
- // take next provider
- ServiceProvider provider = next;
- next = null;
-
- // attempt to load provider
- Module module = provider.module();
- String cn = provider.providerName();
- Class> clazz = loadProviderInModule(module, cn);
- return new ProviderImpl
Set
return names.iterator();
}
- private boolean hasNextService() {
- if (nextClass != null || nextErrorMessage != null) {
- return true;
- }
-
- Class> clazz;
- do {
- if (configs == null) {
- try {
- String fullName = PREFIX + service.getName();
- if (loader == null) {
- configs = ClassLoader.getSystemResources(fullName);
- } else if (loader == ClassLoaders.platformClassLoader()) {
- // The platform classloader doesn't have a class path,
- // but the boot loader might.
- if (BootLoader.hasClassPath()) {
- configs = BootLoader.findResources(fullName);
- } else {
- configs = Collections.emptyEnumeration();
- }
- } else {
- configs = loader.getResources(fullName);
- }
- } catch (IOException x) {
- fail(service, "Error locating configuration files", x);
- }
- }
- while ((pending == null) || !pending.hasNext()) {
- if (!configs.hasMoreElements()) {
- return false;
- }
- pending = parse(configs.nextElement());
- }
- String cn = pending.next();
+ /**
+ * Loads and returns the next provider class.
+ */
+ private Class> nextProviderClass() {
+ if (configs == null) {
try {
- clazz = Class.forName(cn, false, loader);
- } catch (ClassNotFoundException x) {
- // don't throw SCE here to long standing behavior
- nextErrorMessage = "Provider " + cn + " not found";
- return true;
+ String fullName = PREFIX + service.getName();
+ if (loader == null) {
+ configs = ClassLoader.getSystemResources(fullName);
+ } else if (loader == ClassLoaders.platformClassLoader()) {
+ // The platform classloader doesn't have a class path,
+ // but the boot loader might.
+ if (BootLoader.hasClassPath()) {
+ configs = BootLoader.findResources(fullName);
+ } else {
+ configs = Collections.emptyEnumeration();
+ }
+ } else {
+ configs = loader.getResources(fullName);
+ }
+ } catch (IOException x) {
+ fail(service, "Error locating configuration files", x);
}
+ }
+ while ((pending == null) || !pending.hasNext()) {
+ if (!configs.hasMoreElements()) {
+ return null;
+ }
+ pending = parse(configs.nextElement());
+ }
+ String cn = pending.next();
+ try {
+ return Class.forName(cn, false, loader);
+ } catch (ClassNotFoundException x) {
+ fail(service, "Provider " + cn + " not found");
+ return null;
+ }
+ }
- } while (clazz.getModule().isNamed()); // ignore if in named module
+ @SuppressWarnings("unchecked")
+ private boolean hasNextService() {
+ while (nextProvider == null && nextError == null) {
+ try {
+ Class> clazz = nextProviderClass();
+ if (clazz == null)
+ return false;
- nextClass = clazz;
+ if (clazz.getModule().isNamed()) {
+ // ignore class if in named module
+ continue;
+ }
+
+ if (service.isAssignableFrom(clazz)) {
+ Class extends S> type = (Class extends S>) clazz;
+ Constructor extends S> ctor
+ = (Constructor extends S>)getConstructor(clazz);
+ ProviderImpl p = new ProviderImpl(service, type, ctor, acc);
+ nextProvider = (ProviderImpl
if (!hasNextService())
throw new NoSuchElementException();
- // throw any SCE with error recorded by hasNext
- if (nextErrorMessage != null) {
- String msg = nextErrorMessage;
- nextErrorMessage = null;
- fail(service, msg);
+ Provider
/**
* Creates a new service loader for the given service type and class
- * loader.
+ * loader. The service loader locates service providers in both named and
+ * unnamed modules:
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @apiNote If the class path of the class loader includes remote network
+ * URLs then those URLs may be dereferenced in the process of searching for
+ * provider-configuration files.
+ *
+ * the class of the service type
*
@@ -1457,13 +1580,13 @@ public final class ServiceLoader
*
* {@code
- * ServiceLoader.load(service)
+ * ServiceLoader.load(service)
* }
*
* is equivalent to
*
* {@code
- * ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
+ * ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
* }
*
* @apiNote Service loader objects obtained with this method should not be
@@ -1502,7 +1625,7 @@ public final class ServiceLoader
* {@code
- * ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
+ * ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
* }
*
*
}
/**
- * Creates a new service loader for the given service type that loads
- * service providers from modules in the given {@code ModuleLayer} and its
- * ancestors.
+ * Creates a new service loader for the given service type to load service
+ * providers from modules in the given module layer and its ancestors. It
+ * does not locate providers in unnamed modules.
+ *
+ *
+ *
*
* @apiNote Unlike the other load methods defined here, the service type
* is the second parameter. The reason for this is to avoid source
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
index 5d1c97c6d25..95b65f646d8 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
@@ -49,8 +49,10 @@ import java.security.SecureClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.Attributes;
@@ -336,16 +338,43 @@ public class BuiltinClassLoader
}
}
- // search class path
+ // class path (not checked)
Enumeration
+ *
+ *
+ * Starting an Agent from the Command-Line Interface
+ *
+ * {@code
+ * -javaagent:
+ *
+ * where {@code {@code
+ * public static void premain(String agentArgs, Instrumentation inst)
+ * }
+ *
+ * {@code
+ * public static void premain(String agentArgs)
+ * }
+
+ * Starting an Agent After VM Startup
+ *
+ *
+ *
+ *
+ *
+ * {@code
+ * public static void agentmain(String agentArgs, Instrumentation inst)
+ * }
+ *
+ * {@code
+ * public static void agentmain(String agentArgs)
+ * }
+ *
+ * Including an Agent in an Executable JAR file
+ *
+ * {@code
+ * public static void agentmain(String agentArgs, Instrumentation inst)
+ * }
+ *
+ * {@code
+ * public static void agentmain(String agentArgs)
+ * }
+ *
+ * Loading agent classes and the modules/classes available to the agent
+ * class
+ *
+ *
+ *
+ *
+ *
+ * Manifest Attributes
+ *
+ *
+ *
+ *
+ *
+ *
Instrumenting code in modules
+ *
+ * Package Specification
-
-Command-Line Interface
-
-
-
-jarpath is the path to the agent JAR file.
-options is the agent options.
-This switch may be used multiple times on the same command-line,
-thus creating multiple agents.
-More than one agent may use the same jarpath.
-An agent JAR file must conform to the JAR file specification.
-
--javaagent:
jarpath[=
options]
-Premain-Class
. The
-value of this attribute is the name of the agent class. The agent class must implement a
-public static premain
method similar in principle to the main
application
-entry point. After the Java Virtual Machine (JVM) has initialized, each premain
method
-will be called in the order the agents were specified, then the real application
-main
method will be called.
-Each premain
method must return in order for the startup sequence to proceed.
-
-premain
method has one of two possible signatures. The JVM first attempts to
-invoke the following method on the agent class:
-
-
-
-
-public static void
-premain(String agentArgs, Instrumentation inst);
-
-
-
-
-public static void
-premain(String agentArgs);
-
-agentmain
method for use when the agent is started
-after VM startup. When the agent is started using a command-line option, the agentmain
-method is not invoked.
-
-
-main
method.
-The system class loader must support a mechanism to add an agent JAR file to the system class path.
-If it is a custom system class loader then it must define the
-appendToClassPathForInstrumentation
method as specified in
-{@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}.
-The premain
methods will be run under the same security and classloader
-rules as the application main
method.
-There are no modeling restrictions on what the agent premain
method may do.
-Anything application main
can do, including creating threads, is legal from
-premain
.
-
-
-agentArgs
parameter.
-The agent options are passed as a single string,
-any additional parsing should be performed by the agent itself.
-
-premain
method), the JVM will abort.
-If a premain
method throws an uncaught exception, the JVM will abort.
-
-
-Starting Agents After VM Startup
-
-
-main
method has already been invoked. In cases where an implementation
-supports the starting of agents after the VM has started the following applies:
-
-
-
-
-Agent-Class
.
- The value of this attribute is the name of the agent class. agentmain
method. appendToClassPathForInstrumentation
method as specified in
- {@link Instrumentation#appendToSystemClassLoaderSearch appendToSystemClassLoaderSearch}.main
method. The agent class is loaded and the
-JVM attempts to invoke the agentmain
method. The JVM first attempts to invoke
-the following method on the agent class:
-
-
-
-
-public static void
-agentmain(String agentArgs, Instrumentation inst);
-
-
-
-
-public static void
-agentmain(String agentArgs);
-
-premain
method for use when the agent is started
-using a command-line option. When the agent is started after VM startup the premain
-method is not invoked.
-
-
-agentArgs
parameter.
-The agent options are passed as a single string,
-any additional parsing should be performed by the agent itself.
-
-agentmain
method should do any necessary initialization
-required to start the agent. When startup is complete the method should
-return. If the agent cannot be started
-(for example, because the agent class cannot be loaded,
-or because the agent class does not have a conformant agentmain
method), the JVM will
-not abort. If the agentmain
method throws an uncaught exception it will be ignored.
-
-
-Deploying Agents in Executable JAR file
-
-The JAR File Specification defines manifest attributes for standalone applications that are
-bundled as executable JAR files. If an implementation supports a mechanism to start
-an application as an executable JAR then the main manifest may include the
-Launcher-Agent-Class
attribute to specify the class name
-of an agent to start before the application main
method is invoked. The Java
-virtual machine attempts to invoke the following method on the agent class:
-
-
-
-
-public static void
- agentmain(String agentArgs, Instrumentation inst);
-
-
-
-
-public static void
- agentmain(String agentArgs);
-
-agentArgs
parameter is always the empty string.
-
-agentmain
method should do any necessary initialization
-required to start the agent and return. If the agent cannot be started, for
-example the agent class cannot be loaded, the agent class does not define a
-conformant agentmain
method, or the agentmain
method
-throws an uncaught exception or error, the JVM will abort.
-
-
-Visibility
-
-The types visible to the agent class are the types visible to the system class
-loader. They minimally include the types in packages exported by
-java.base and
-java.instrument.
-Whether all {@linkplain ClassLoader#getPlatformClassLoader() platform classes}
-are visible or not will depend on the initial module or application.
-
-Boot-Class-Path
attribute
-specified below) can only link to types defined to the bootstrap class loader.
-There is no guarantee that all platform classes are visible to the boot class
-loader.
-
-
-Manifest Attributes
-
-The following manifest attributes are defined for an agent JAR file:
-
-
-
-
-
-Premain-Class
premain
method.
- When an agent is specified at JVM launch time this attribute
- is required. If the attribute is not present the JVM will abort.
- Note: this is a class name, not a file name or path.
-Agent-Class
agentmain
method.
- This attribute is required, if it is not present the agent
- will not be started.
- Note: this is a class name, not a file name or path.
-Launcher-Agent-Class
main
method is invoked.
-Boot-Class-Path
Can-Redefine-Classes
true
or false
, case irrelevant).
- Is the ability to redefine classes
- needed by this agent.
- Values other than true
are considered false
.
- This attribute is optional, the default is false
.
-Can-Retransform-Classes
true
or false
, case irrelevant).
- Is the ability to retransform classes
- needed by this agent.
- Values other than true
are considered false
.
- This attribute is optional, the default is false
.
-Can-Set-Native-Method-Prefix
true
or false
, case irrelevant).
- Is the ability to set native method prefix needed by this agent.
- Values other than true
are considered false
.
- This attribute is optional, the default is false
.
-Premain-Class
and Agent-Class
-attributes present in the manifest. When the agent is started on the command-line using
-the -javaagent
option then the Premain-Class
attribute
-specifies the name of the agent class and the Agent-Class
attribute is
-ignored. Similarly, if the agent is started sometime after the VM has started, then
-the Agent-Class
attribute specifies the name of the agent class
-(the value of Premain-Class
attribute is ignored).
-
-
-Instrumenting code in modules
-
-As an aid to agents that deploy supporting classes on the search path of the
-bootstrap class loader, or the search path of the class loader that loads
-the main agent class, the Java virtual machine arranges for the module of
-transformed classes to read the unnamed module of both class loaders.
-
-
-Related Documentation
-
-For tool documentation, please see:
-
-
-@since 1.5
-@revised 1.6
-
-
-
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
index bdd8b42db8c..5e1e64e3939 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
@@ -34,6 +34,10 @@ import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Version;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
@@ -41,13 +45,17 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.IntSupplier;
+import java.util.stream.Collectors;
import jdk.internal.module.Checks;
import jdk.internal.module.ClassFileAttributes;
import jdk.internal.module.ClassFileConstants;
+import jdk.internal.module.IllegalAccessMaps;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfo.Attributes;
import jdk.internal.module.ModuleInfoExtender;
@@ -601,6 +609,10 @@ public final class SystemModulesPlugin implements Plugin {
// generate SystemModules::moduleResolutions
genModuleResolutionsMethod();
+ // generate SystemModules::concealedPackagesToOpen and
+ // SystemModules::exportedPackagesToOpen
+ genXXXPackagesToOpenMethods();
+
return cw;
}
@@ -733,6 +745,96 @@ public final class SystemModulesPlugin implements Plugin {
mresmv.visitEnd();
}
+ /**
+ * Generate SystemModules::concealedPackagesToOpen and
+ * SystemModules::exportedPackagesToOpen methods.
+ */
+ private void genXXXPackagesToOpenMethods() {
+ List providers = ServiceLoader.load(S.class).stream()
+ .map(ServiceLoader.Provider::get)
+ .collect(Collectors.toList());
+ if (providers.size() != 3)
+ throw new RuntimeException("Expected 3 providers");
+ }
+
+ /**
+ * Service type
+ */
+ public static interface S {
+ }
+
+ /**
+ * Base implementation, its static provider method should never be called
+ */
+ public static class BaseProvider implements S {
+ protected BaseProvider() { }
+ public static S provider() {
+ throw new RuntimeException("Should not get here");
+ }
+ }
+
+ /**
+ * Provider implementation with public constructor.
+ */
+ public static class P1 extends BaseProvider {
+ public P1() { }
+ }
+
+ /**
+ * Provider implementation with static factory method.
+ */
+ public static class P2 extends BaseProvider {
+ private P2() { }
+ public static P2 provider() {
+ return new P2();
+ }
+ }
+
+ /**
+ * Provider implementation with static factory method and public
+ * constructor.
+ */
+ public static class P3 extends BaseProvider {
+ public P3() {
+ throw new RuntimeException("Should not get here");
+ }
+ private P3(int x) { }
+ public static S provider() {
+ return new P3(0);
+ }
+ }
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/module-info.java b/jdk/test/java/util/ServiceLoader/modules/bananascript/module-info.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/bananascript/module-info.java
rename to jdk/test/java/util/ServiceLoader/modules/bananascript/module-info.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScript.java b/jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScript.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScript.java
rename to jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScript.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScriptEngineFactory.java b/jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScriptEngineFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScriptEngineFactory.java
rename to jdk/test/java/util/ServiceLoader/modules/bananascript/org/banana/BananaScriptEngineFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/p1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/p1/module-info.java
new file mode 100644
index 00000000000..e3ed70f88e3
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+module p1 {
+ requires s1;
+ provides p.S with q.P;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/p1/q/P.java b/jdk/test/java/util/ServiceLoader/modules/p1/q/P.java
new file mode 100644
index 00000000000..26a0186ac25
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p1/q/P.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, 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 q;
+
+import p.S;
+
+public class P implements S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/p2/module-info.java b/jdk/test/java/util/ServiceLoader/modules/p2/module-info.java
new file mode 100644
index 00000000000..aeb81471512
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p2/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+module p2 {
+ requires s2;
+ provides p.S with q.P;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/p2/q/P.java b/jdk/test/java/util/ServiceLoader/modules/p2/q/P.java
new file mode 100644
index 00000000000..26a0186ac25
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/p2/q/P.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, 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 q;
+
+import p.S;
+
+public class P implements S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/s1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/s1/module-info.java
new file mode 100644
index 00000000000..784ad40a8df
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s1/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+module s1 {
+ exports p;
+ uses p.S;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/s1/p/S.java b/jdk/test/java/util/ServiceLoader/modules/s1/p/S.java
new file mode 100644
index 00000000000..e9ecc6f9949
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s1/p/S.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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 p;
+
+public interface S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/s2/module-info.java b/jdk/test/java/util/ServiceLoader/modules/s2/module-info.java
new file mode 100644
index 00000000000..b1d8f3ed462
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s2/module-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+module s2 {
+ exports p;
+}
diff --git a/jdk/test/java/util/ServiceLoader/modules/s2/p/S.java b/jdk/test/java/util/ServiceLoader/modules/s2/p/S.java
new file mode 100644
index 00000000000..e9ecc6f9949
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/s2/p/S.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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 p;
+
+public interface S { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/test1/module-info.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test1/module-info.java
rename to jdk/test/java/util/ServiceLoader/modules/test1/module-info.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/ProviderFactory.java b/jdk/test/java/util/ServiceLoader/modules/test1/p/ProviderFactory.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test1/p/ProviderFactory.java
rename to jdk/test/java/util/ServiceLoader/modules/test1/p/ProviderFactory.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/Service.java b/jdk/test/java/util/ServiceLoader/modules/test1/p/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test1/p/Service.java
rename to jdk/test/java/util/ServiceLoader/modules/test1/p/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test2/module-info.java b/jdk/test/java/util/ServiceLoader/modules/test2/module-info.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test2/module-info.java
rename to jdk/test/java/util/ServiceLoader/modules/test2/module-info.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Provider.java b/jdk/test/java/util/ServiceLoader/modules/test2/p/Provider.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Provider.java
rename to jdk/test/java/util/ServiceLoader/modules/test2/p/Provider.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Service.java b/jdk/test/java/util/ServiceLoader/modules/test2/p/Service.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Service.java
rename to jdk/test/java/util/ServiceLoader/modules/test2/p/Service.java
diff --git a/jdk/test/java/util/ServiceLoader/nouses/NoUsesTest.java b/jdk/test/java/util/ServiceLoader/nouses/NoUsesTest.java
new file mode 100644
index 00000000000..641574b77d1
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/nouses/NoUsesTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 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 java.scripting
+ * @build test/*
+ * @run main/othervm test/p.Main
+ * @summary Basic test of ServiceLoader.load from named modules that does
+ * does delcare the use
+ */
diff --git a/jdk/test/java/util/ServiceLoader/nouses/test/module-info.java b/jdk/test/java/util/ServiceLoader/nouses/test/module-info.java
new file mode 100644
index 00000000000..1bcf5944728
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/nouses/test/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+module test {
+ exports p;
+ requires java.scripting;
+}
diff --git a/jdk/test/java/util/ServiceLoader/nouses/test/p/Main.java b/jdk/test/java/util/ServiceLoader/nouses/test/p/Main.java
new file mode 100644
index 00000000000..ce8ee0fcbb6
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/nouses/test/p/Main.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, 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 p;
+
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import javax.script.ScriptEngineFactory;
+
+public class Main {
+
+ public static void main(String[] args) {
+ Module thisModule = Main.class.getModule();
+ assertTrue(thisModule.isNamed());
+
+ // this module does not declare that it uses ScriptEngineFactory
+ assertFalse(thisModule.canUse(ScriptEngineFactory.class));
+ try {
+ ServiceLoader.load(ScriptEngineFactory.class);
+ assertTrue(false);
+ } catch (ServiceConfigurationError expected) { }
+
+ // invoke addUses and retry
+ thisModule.addUses(ScriptEngineFactory.class);
+ ServiceLoader.load(ScriptEngineFactory.class).findFirst();
+ }
+
+ static void assertFalse(boolean value) {
+ if (value) throw new RuntimeException();
+ }
+
+ static void assertTrue(boolean value) {
+ if (!value) throw new RuntimeException();
+ }
+}
diff --git a/jdk/test/java/util/ServiceLoader/security/SecurityTest.java b/jdk/test/java/util/ServiceLoader/security/SecurityTest.java
new file mode 100644
index 00000000000..5a680355277
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/security/SecurityTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, 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
+ * @build test/*
+ * @run testng/othervm test/p.Tests
+ * @summary Tests to exercise ServiceLoader with a security manager
+ */
diff --git a/jdk/test/java/util/ServiceLoader/security/test/module-info.java b/jdk/test/java/util/ServiceLoader/security/test/module-info.java
new file mode 100644
index 00000000000..f9d02cfb345
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/security/test/module-info.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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 p.Tests.*;
+
+module test {
+ uses S1;
+ uses S2;
+ provides S1 with P1;
+ provides S2 with P2;
+ requires testng;
+ exports p to testng;
+}
diff --git a/jdk/test/java/util/ServiceLoader/security/test/p/Tests.java b/jdk/test/java/util/ServiceLoader/security/test/p/Tests.java
new file mode 100644
index 00000000000..bccc14cc9bd
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/security/test/p/Tests.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2017, 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 p;
+
+import java.security.AccessControlContext;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
+import static java.security.AccessController.doPrivileged;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeTest;
+import static org.testng.Assert.*;
+
+/**
+ * Basic tests with a security manager to ensure that the provider code
+ * is run with permissions restricted by whatever created the ServiceLoader
+ * object.
+ */
+
+public class Tests {
+
+ static final Permission PERM = new RuntimePermission("eatMuffin");
+
+ static