8178404: jlink --suggest-providers should list providers from observable modules
Reviewed-by: alanb
This commit is contained in:
parent
82a6322c55
commit
05e16f5153
@ -158,7 +158,7 @@ public final class Jlink {
|
||||
*
|
||||
* @param output Output directory, must not exist.
|
||||
* @param modulepaths Modules paths
|
||||
* @param modules Root modules to resolve
|
||||
* @param modules The possibly-empty set of root modules to resolve
|
||||
* @param limitmods Limit the universe of observable modules
|
||||
* @param endian Jimage byte order. Native order by default
|
||||
*/
|
||||
@ -170,13 +170,10 @@ public final class Jlink {
|
||||
if (Objects.requireNonNull(modulepaths).isEmpty()) {
|
||||
throw new IllegalArgumentException("Empty module path");
|
||||
}
|
||||
if (Objects.requireNonNull(modules).isEmpty()) {
|
||||
throw new IllegalArgumentException("Empty modules");
|
||||
}
|
||||
|
||||
this.output = output;
|
||||
this.modulepaths = modulepaths;
|
||||
this.modules = modules;
|
||||
this.modules = Objects.requireNonNull(modules);
|
||||
this.limitmods = Objects.requireNonNull(limitmods);
|
||||
this.endian = Objects.requireNonNull(endian);
|
||||
this.finder = moduleFinder();
|
||||
|
@ -40,7 +40,20 @@ import java.nio.ByteOrder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -331,11 +344,6 @@ public class JlinkTask {
|
||||
// the token for "all modules on the module path"
|
||||
private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
|
||||
private JlinkConfiguration initJlinkConfig() throws BadArgs {
|
||||
if (options.addMods.isEmpty()) {
|
||||
throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
|
||||
.showUsage(true);
|
||||
}
|
||||
|
||||
Set<String> roots = new HashSet<>();
|
||||
for (String mod : options.addMods) {
|
||||
if (mod.equals(ALL_MODULE_PATH)) {
|
||||
@ -369,6 +377,10 @@ public class JlinkTask {
|
||||
if (options.output == null) {
|
||||
throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
|
||||
}
|
||||
if (options.addMods.isEmpty()) {
|
||||
throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
|
||||
.showUsage(true);
|
||||
}
|
||||
|
||||
// First create the image provider
|
||||
ImageProvider imageProvider = createImageProvider(config,
|
||||
@ -430,7 +442,7 @@ public class JlinkTask {
|
||||
// print modules to be linked in
|
||||
cf.modules().stream()
|
||||
.sorted(Comparator.comparing(ResolvedModule::name))
|
||||
.forEach(rm -> log.format("module %s (%s)%n",
|
||||
.forEach(rm -> log.format("%s %s%n",
|
||||
rm.name(), rm.reference().location().get()));
|
||||
|
||||
// print provider info
|
||||
@ -505,16 +517,22 @@ public class JlinkTask {
|
||||
|
||||
/*
|
||||
* Returns a map of each service type to the modules that use it
|
||||
* It will include services that are provided by a module but may not used
|
||||
* by any of the observable modules.
|
||||
*/
|
||||
private static Map<String, Set<String>> uses(Set<ModuleReference> modules) {
|
||||
// collects the services used by the modules and print uses
|
||||
Map<String, Set<String>> uses = new HashMap<>();
|
||||
Map<String, Set<String>> services = new HashMap<>();
|
||||
modules.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.forEach(md -> md.uses().forEach(s ->
|
||||
uses.computeIfAbsent(s, _k -> new HashSet<>()).add(md.name()))
|
||||
);
|
||||
return uses;
|
||||
.forEach(md -> {
|
||||
// include services that may not be used by any observable modules
|
||||
md.provides().forEach(p ->
|
||||
services.computeIfAbsent(p.service(), _k -> new HashSet<>()));
|
||||
md.uses().forEach(s -> services.computeIfAbsent(s, _k -> new HashSet<>())
|
||||
.add(md.name()));
|
||||
});
|
||||
return services;
|
||||
}
|
||||
|
||||
private static void printProviders(PrintWriter log,
|
||||
@ -524,17 +542,16 @@ public class JlinkTask {
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints the providers that are used by the services specified in
|
||||
* the given modules.
|
||||
* Prints the providers that are used by the specified services.
|
||||
*
|
||||
* The specified uses maps a service type name to the modules
|
||||
* using the service type and that may or may not be present
|
||||
* the given modules.
|
||||
* The specified services maps a service type name to the modules
|
||||
* using the service type which may be empty if no observable module uses
|
||||
* that service.
|
||||
*/
|
||||
private static void printProviders(PrintWriter log,
|
||||
String header,
|
||||
Set<ModuleReference> modules,
|
||||
Map<String, Set<String>> uses) {
|
||||
Map<String, Set<String>> serviceToUses) {
|
||||
if (modules.isEmpty())
|
||||
return;
|
||||
|
||||
@ -544,7 +561,7 @@ public class JlinkTask {
|
||||
.map(ModuleReference::descriptor)
|
||||
.forEach(md -> {
|
||||
md.provides().stream()
|
||||
.filter(p -> uses.containsKey(p.service()))
|
||||
.filter(p -> serviceToUses.containsKey(p.service()))
|
||||
.forEach(p -> providers.computeIfAbsent(p.service(), _k -> new HashSet<>())
|
||||
.add(md));
|
||||
});
|
||||
@ -564,11 +581,18 @@ public class JlinkTask {
|
||||
.forEach(md ->
|
||||
md.provides().stream()
|
||||
.filter(p -> p.service().equals(service))
|
||||
.forEach(p -> log.format(" module %s provides %s, used by %s%n",
|
||||
md.name(), p.service(),
|
||||
uses.get(p.service()).stream()
|
||||
.sorted()
|
||||
.collect(Collectors.joining(","))))
|
||||
.forEach(p -> {
|
||||
String usedBy;
|
||||
if (serviceToUses.get(p.service()).isEmpty()) {
|
||||
usedBy = "not used by any observable module";
|
||||
} else {
|
||||
usedBy = serviceToUses.get(p.service()).stream()
|
||||
.sorted()
|
||||
.collect(Collectors.joining(",", "used by ", ""));
|
||||
}
|
||||
log.format(" %s provides %s %s%n",
|
||||
md.name(), p.service(), usedBy);
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -589,25 +613,21 @@ public class JlinkTask {
|
||||
|
||||
ModuleFinder finder = config.finder();
|
||||
if (args.isEmpty()) {
|
||||
// print providers used by the modules resolved without service binding
|
||||
Configuration cf = config.resolve();
|
||||
Set<ModuleReference> mrefs = cf.modules().stream()
|
||||
.map(ResolvedModule::reference)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// print providers used by the observable modules without service binding
|
||||
Set<ModuleReference> mrefs = finder.findAll();
|
||||
// print uses of the modules that would be linked into the image
|
||||
mrefs.stream()
|
||||
.sorted(Comparator.comparing(mref -> mref.descriptor().name()))
|
||||
.forEach(mref -> {
|
||||
ModuleDescriptor md = mref.descriptor();
|
||||
log.format("module %s located (%s)%n", md.name(),
|
||||
log.format("%s %s%n", md.name(),
|
||||
mref.location().get());
|
||||
md.uses().stream().sorted()
|
||||
.forEach(s -> log.format(" uses %s%n", s));
|
||||
});
|
||||
|
||||
String msg = String.format("%n%s:", taskHelper.getMessage("suggested.providers.header"));
|
||||
printProviders(log, msg, finder.findAll(), uses(mrefs));
|
||||
printProviders(log, msg, mrefs, uses(mrefs));
|
||||
|
||||
} else {
|
||||
// comma-separated service types, if specified
|
||||
@ -620,17 +640,22 @@ public class JlinkTask {
|
||||
.anyMatch(names::contains))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// the specified services may or may not be in the modules that
|
||||
// would be linked in. So find uses declared in all observable modules
|
||||
Map<String, Set<String>> uses = uses(finder.findAll());
|
||||
// find the modules that uses the specified services
|
||||
Map<String, Set<String>> uses = new HashMap<>();
|
||||
names.forEach(s -> uses.computeIfAbsent(s, _k -> new HashSet<>()));
|
||||
finder.findAll().stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.forEach(md -> md.uses().stream()
|
||||
.filter(names::contains)
|
||||
.forEach(s -> uses.get(s).add(md.name())));
|
||||
|
||||
// check if any name given on the command line are unused service
|
||||
// check if any name given on the command line are not provided by any module
|
||||
mrefs.stream()
|
||||
.flatMap(mref -> mref.descriptor().provides().stream()
|
||||
.map(ModuleDescriptor.Provides::service))
|
||||
.forEach(names::remove);
|
||||
if (!names.isEmpty()) {
|
||||
log.println(taskHelper.getMessage("warn.unused.services",
|
||||
log.println(taskHelper.getMessage("warn.provider.notfound",
|
||||
toString(names)));
|
||||
}
|
||||
|
||||
|
@ -57,12 +57,12 @@ main.opt.launcher=\
|
||||
\ if specified
|
||||
|
||||
main.opt.bind-services=\
|
||||
\ --bind-services Do full service binding
|
||||
\ --bind-services Link in service provider modules and\n\
|
||||
\ their dependences
|
||||
|
||||
main.opt.suggest-providers=\
|
||||
\ --suggest-providers [<name>,...] Suggest providers of services used by\n\
|
||||
\ the modules that would be linked, or\n\
|
||||
\ of the given service types
|
||||
\ --suggest-providers [<name>,...] Suggest providers that implement the\n\
|
||||
\ given service types from the module path
|
||||
|
||||
main.command.files=\
|
||||
\ @<filename> Read options from file
|
||||
@ -138,7 +138,7 @@ err.signing=signed modular JAR {0} is currently not supported,\
|
||||
warn.signing=WARNING: signed modular JAR {0} is currently not supported
|
||||
warn.invalid.arg=invalid classname or pathname not exist: {0}
|
||||
warn.split.package=package {0} defined in {1} {2}
|
||||
warn.unused.services=Services specified in --suggest-providers not used: {0}
|
||||
warn.provider.notfound=No provider found for service specified to --suggest-providers: {0}
|
||||
no.suggested.providers=--bind-services option is specified. No additional providers suggested.
|
||||
suggested.providers.header=Suggested providers
|
||||
providers.header=Providers
|
||||
|
@ -33,7 +33,6 @@ import java.util.spi.ToolProvider;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static jdk.testlibrary.Asserts.assertTrue;
|
||||
import static jdk.testlibrary.ProcessTools.*;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
@ -114,7 +113,7 @@ public class BindServices {
|
||||
"--module-path", MODULE_PATH,
|
||||
"--add-modules", "m1",
|
||||
"--bind-services",
|
||||
"--limit-modules", "m1,m2,m3,java.base");
|
||||
"--limit-modules", "m1,m2,m3");
|
||||
|
||||
testImage(dir, "m1", "m2", "m3");
|
||||
}
|
||||
@ -131,16 +130,18 @@ public class BindServices {
|
||||
"--add-modules", "m1",
|
||||
"--bind-services",
|
||||
"--verbose",
|
||||
"--limit-modules", "m1,m2,m3,java.base").output();
|
||||
"--limit-modules", "m1,m2,m3").output();
|
||||
|
||||
List<String> expected = List.of(
|
||||
"module m1 (" + MODS_DIR.resolve("m1").toUri().toString() + ")",
|
||||
"module m2 (" + MODS_DIR.resolve("m2").toUri().toString() + ")",
|
||||
"module m3 (" + MODS_DIR.resolve("m3").toUri().toString() + ")",
|
||||
"module m1 provides p1.S, used by m1",
|
||||
"module m2 provides p1.S, used by m1",
|
||||
"module m2 provides p2.T, used by m2",
|
||||
"module m3 provides p2.T, used by m2"
|
||||
"m1 " + MODS_DIR.resolve("m1").toUri().toString(),
|
||||
"m2 " + MODS_DIR.resolve("m2").toUri().toString(),
|
||||
"m3 " + MODS_DIR.resolve("m3").toUri().toString(),
|
||||
"java.base provides java.nio.file.spi.FileSystemProvider used by java.base",
|
||||
"m1 provides p1.S used by m1",
|
||||
"m2 provides p1.S used by m1",
|
||||
"m2 provides p2.T used by m2",
|
||||
"m3 provides p2.T used by m2",
|
||||
"m3 provides p3.S not used by any observable module"
|
||||
);
|
||||
|
||||
assertTrue(output.containsAll(expected));
|
||||
|
@ -33,8 +33,6 @@ import java.util.spi.ToolProvider;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static jdk.testlibrary.Asserts.assertTrue;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
@ -85,34 +83,102 @@ public class SuggestProviders {
|
||||
}
|
||||
}
|
||||
|
||||
// check a subset of services used by java.base
|
||||
private final List<String> JAVA_BASE_USES = List.of(
|
||||
"uses java.lang.System$LoggerFinder",
|
||||
"uses java.net.ContentHandlerFactory",
|
||||
"uses java.net.spi.URLStreamHandlerProvider",
|
||||
"uses java.nio.channels.spi.AsynchronousChannelProvider",
|
||||
"uses java.nio.channels.spi.SelectorProvider",
|
||||
"uses java.nio.charset.spi.CharsetProvider",
|
||||
"uses java.nio.file.spi.FileSystemProvider",
|
||||
"uses java.nio.file.spi.FileTypeDetector",
|
||||
"uses java.security.Provider",
|
||||
"uses java.util.spi.ToolProvider"
|
||||
);
|
||||
|
||||
private final List<String> JAVA_BASE_PROVIDERS = List.of(
|
||||
"java.base provides java.nio.file.spi.FileSystemProvider used by java.base"
|
||||
);
|
||||
|
||||
private final List<String> SYSTEM_PROVIDERS = List.of(
|
||||
"jdk.charsets provides java.nio.charset.spi.CharsetProvider used by java.base",
|
||||
"jdk.compiler provides java.util.spi.ToolProvider used by java.base",
|
||||
"jdk.compiler provides javax.tools.JavaCompiler used by java.compiler",
|
||||
"jdk.jlink provides jdk.tools.jlink.plugin.Plugin used by jdk.jlink",
|
||||
"jdk.jlink provides java.util.spi.ToolProvider used by java.base"
|
||||
);
|
||||
|
||||
private final List<String> APP_USES = List.of(
|
||||
"uses p1.S",
|
||||
"uses p2.T"
|
||||
);
|
||||
|
||||
private final List<String> APP_PROVIDERS = List.of(
|
||||
"m1 provides p1.S used by m1",
|
||||
"m2 provides p1.S used by m1",
|
||||
"m2 provides p2.T used by m2",
|
||||
"m3 provides p2.T used by m2",
|
||||
"m3 provides p3.S not used by any observable module"
|
||||
);
|
||||
|
||||
@Test
|
||||
public void suggestProviders() throws Throwable {
|
||||
if (!hasJmods()) return;
|
||||
|
||||
List<String> output = JLink.run("--module-path", MODULE_PATH,
|
||||
"--suggest-providers").output();
|
||||
|
||||
Stream<String> uses =
|
||||
Stream.concat(JAVA_BASE_USES.stream(), APP_USES.stream());
|
||||
Stream<String> providers =
|
||||
Stream.concat(SYSTEM_PROVIDERS.stream(), APP_PROVIDERS.stream());
|
||||
|
||||
assertTrue(output.containsAll(Stream.concat(uses, providers)
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
/**
|
||||
* find providers from the observable modules and --add-modules has no
|
||||
* effect on the suggested providers
|
||||
*/
|
||||
@Test
|
||||
public void observableModules() throws Throwable {
|
||||
if (!hasJmods()) return;
|
||||
|
||||
List<String> output = JLink.run("--module-path", MODULE_PATH,
|
||||
"--add-modules", "m1",
|
||||
"--suggest-providers").output();
|
||||
// check a subset of services used by java.base
|
||||
List<String> expected = List.of(
|
||||
"uses java.lang.System$LoggerFinder",
|
||||
"uses java.net.ContentHandlerFactory",
|
||||
"uses java.net.spi.URLStreamHandlerProvider",
|
||||
"uses java.nio.channels.spi.AsynchronousChannelProvider",
|
||||
"uses java.nio.channels.spi.SelectorProvider",
|
||||
"uses java.nio.charset.spi.CharsetProvider",
|
||||
"uses java.nio.file.spi.FileSystemProvider",
|
||||
"uses java.nio.file.spi.FileTypeDetector",
|
||||
"uses java.security.Provider",
|
||||
"uses java.util.spi.ToolProvider",
|
||||
"uses p1.S",
|
||||
"module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base",
|
||||
"module jdk.compiler provides java.util.spi.ToolProvider, used by java.base",
|
||||
"module jdk.jlink provides java.util.spi.ToolProvider, used by java.base",
|
||||
"module m1 provides p1.S, used by m1",
|
||||
"module m2 provides p1.S, used by m1"
|
||||
|
||||
Stream<String> uses =
|
||||
Stream.concat(JAVA_BASE_USES.stream(), Stream.of("uses p1.S"));
|
||||
Stream<String> providers =
|
||||
Stream.concat(SYSTEM_PROVIDERS.stream(), APP_PROVIDERS.stream());
|
||||
|
||||
assertTrue(output.containsAll(Stream.concat(uses, providers)
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
/**
|
||||
* find providers from the observable modules with --limit-modules
|
||||
*/
|
||||
@Test
|
||||
public void limitModules() throws Throwable {
|
||||
if (!hasJmods()) return;
|
||||
|
||||
List<String> output = JLink.run("--module-path", MODULE_PATH,
|
||||
"--limit-modules", "m1",
|
||||
"--suggest-providers").output();
|
||||
|
||||
Stream<String> uses =
|
||||
Stream.concat(JAVA_BASE_USES.stream(), Stream.of("uses p1.S"));
|
||||
Stream<String> providers =
|
||||
Stream.concat(JAVA_BASE_PROVIDERS.stream(),
|
||||
Stream.of("m1 provides p1.S used by m1")
|
||||
);
|
||||
|
||||
assertTrue(output.containsAll(expected));
|
||||
assertTrue(output.containsAll(Stream.concat(uses, providers)
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -121,20 +187,17 @@ public class SuggestProviders {
|
||||
|
||||
List<String> output =
|
||||
JLink.run("--module-path", MODULE_PATH,
|
||||
"--add-modules", "m1",
|
||||
"--suggest-providers",
|
||||
"java.nio.charset.spi.CharsetProvider,p1.S,p2.T").output();
|
||||
"java.nio.charset.spi.CharsetProvider,p1.S").output();
|
||||
|
||||
System.out.println(output);
|
||||
List<String> expected = List.of(
|
||||
"module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base",
|
||||
"module m1 provides p1.S, used by m1",
|
||||
"module m2 provides p1.S, used by m1",
|
||||
"module m2 provides p2.T, used by m2",
|
||||
"module m3 provides p2.T, used by m2"
|
||||
Stream<String> expected = Stream.concat(
|
||||
Stream.of("jdk.charsets provides java.nio.charset.spi.CharsetProvider used by java.base"),
|
||||
Stream.of("m1 provides p1.S used by m1",
|
||||
"m2 provides p1.S used by m1")
|
||||
);
|
||||
|
||||
assertTrue(output.containsAll(expected));
|
||||
assertTrue(output.containsAll(expected.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -143,15 +206,30 @@ public class SuggestProviders {
|
||||
|
||||
List<String> output =
|
||||
JLink.run("--module-path", MODULE_PATH,
|
||||
"--add-modules", "m1",
|
||||
"--suggest-providers",
|
||||
"nonExistentType").output();
|
||||
"--suggest-providers",
|
||||
"p3.S").output();
|
||||
|
||||
System.out.println(output);
|
||||
List<String> expected = List.of(
|
||||
"Services specified in --suggest-providers not used: nonExistentType"
|
||||
"m3 provides p3.S not used by any observable module"
|
||||
);
|
||||
assertTrue(output.containsAll(expected));
|
||||
|
||||
// should not print other services m3 provides
|
||||
assertFalse(output.contains("m3 provides p2.T used by m2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentService() throws Throwable {
|
||||
if (!hasJmods()) return;
|
||||
|
||||
List<String> output =
|
||||
JLink.run("--module-path", MODULE_PATH,
|
||||
"--suggest-providers",
|
||||
"nonExistentType").output();
|
||||
|
||||
List<String> expected = List.of(
|
||||
"No provider found for service specified to --suggest-providers: nonExistentType"
|
||||
);
|
||||
assertTrue(output.containsAll(expected));
|
||||
}
|
||||
|
||||
@ -161,9 +239,7 @@ public class SuggestProviders {
|
||||
|
||||
List<String> output =
|
||||
JLink.run("--module-path", MODULE_PATH,
|
||||
"--add-modules", "m1",
|
||||
"--bind-services",
|
||||
"--limit-modules", "m1,m2,m3,java.base",
|
||||
"--suggest-providers").output();
|
||||
|
||||
String expected = "--bind-services option is specified. No additional providers suggested.";
|
||||
|
@ -24,4 +24,5 @@
|
||||
module m3 {
|
||||
requires m2;
|
||||
provides p2.T with p3.Impl;
|
||||
provides p3.S with p3.MyProvider;
|
||||
}
|
||||
|
29
jdk/test/tools/jlink/bindservices/src/m3/p3/MyProvider.java
Normal file
29
jdk/test/tools/jlink/bindservices/src/m3/p3/MyProvider.java
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
package p3;
|
||||
|
||||
public class MyProvider implements S {
|
||||
public void run() {
|
||||
}
|
||||
}
|
28
jdk/test/tools/jlink/bindservices/src/m3/p3/S.java
Normal file
28
jdk/test/tools/jlink/bindservices/src/m3/p3/S.java
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 p3;
|
||||
|
||||
public interface S {
|
||||
void run();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user