2626
2727import static com .oracle .svm .core .SubstrateOptions .IncludeAllFromClassPath ;
2828import static com .oracle .svm .core .SubstrateOptions .IncludeAllFromModule ;
29+ import static com .oracle .svm .core .SubstrateOptions .IncludeAllFromPackage ;
2930import static com .oracle .svm .core .SubstrateOptions .IncludeAllFromPath ;
3031import static com .oracle .svm .core .util .VMError .guarantee ;
3132import static com .oracle .svm .core .util .VMError .shouldNotReachHere ;
7475import java .util .stream .Collectors ;
7576import java .util .stream .Stream ;
7677
77- import com .oracle .svm .core .SubstrateUtil ;
7878import org .graalvm .collections .EconomicMap ;
7979import org .graalvm .collections .EconomicSet ;
8080import org .graalvm .collections .MapCursor ;
8181import org .graalvm .nativeimage .impl .AnnotationExtractor ;
8282
8383import com .oracle .svm .core .NativeImageClassLoaderOptions ;
8484import com .oracle .svm .core .SubstrateOptions ;
85+ import com .oracle .svm .core .SubstrateUtil ;
8586import com .oracle .svm .core .option .AccumulatingLocatableMultiOptionValue ;
8687import com .oracle .svm .core .option .HostedOptionKey ;
8788import com .oracle .svm .core .option .LocatableMultiOptionValue .ValueWithOrigin ;
@@ -129,13 +130,15 @@ public final class NativeImageClassLoaderSupport {
129130 public final AnnotationExtractor annotationExtractor ;
130131
131132 private Set <String > javaModuleNamesToInclude ;
133+ private Set <String > javaPackagesToInclude ;
132134 private Set <Path > javaPathsToInclude ;
133135 private boolean includeAllFromClassPath ;
134136
135137 private Optional <LibGraalClassLoaderBase > libGraalLoader ;
136138 private List <ClassLoader > classLoaders ;
137139
138- private final Set <Class <?>> classesToIncludeUnconditionally = Collections .newSetFromMap (new ConcurrentHashMap <>());
140+ private final Set <Class <?>> classesToIncludeUnconditionally = ConcurrentHashMap .newKeySet ();
141+ private final Set <String > includedJavaPackages = ConcurrentHashMap .newKeySet ();
139142
140143 private final Method implAddReadsAllUnnamed = ReflectionUtil .lookupMethod (Module .class , "implAddReadsAllUnnamed" );
141144 private final Method implAddEnableNativeAccess = ReflectionUtil .lookupMethod (Module .class , "implAddEnableNativeAccess" );
@@ -244,7 +247,7 @@ private static Path stringToPath(String path) {
244247 }
245248
246249 public void loadAllClasses (ForkJoinPool executor , ImageClassLoader imageClassLoader ) {
247- guarantee (javaModuleNamesToInclude == null , "This method should be executed only once." );
250+ guarantee (javaModuleNamesToInclude == null && javaPackagesToInclude == null , "This method should be executed only once." );
248251 javaModuleNamesToInclude = Collections .unmodifiableSet (new HashSet <>(IncludeAllFromModule .getValue (parsedHostedOptions ).values ()));
249252 /* Verify all modules are present */
250253 final Set <String > allModules = Stream .concat (modulepathModuleFinder .findAll ().stream (), upgradeAndSystemModuleFinder .findAll ().stream ())
@@ -254,6 +257,8 @@ public void loadAllClasses(ForkJoinPool executor, ImageClassLoader imageClassLoa
254257 .filter (m -> !allModules .contains (m ))
255258 .findAny ().ifPresent (m -> missingFromSetOfEntriesError (m , allModules , "module-path" , IncludeAllFromModule ));
256259
260+ javaPackagesToInclude = Set .copyOf (IncludeAllFromPackage .getValue (parsedHostedOptions ).values ());
261+
257262 javaPathsToInclude = IncludeAllFromPath .getValue (parsedHostedOptions ).values ().stream ()
258263 .map (NativeImageClassLoaderSupport ::stringToPath )
259264 .map (Path ::toAbsolutePath )
@@ -722,32 +727,44 @@ private void run() {
722727 System .out .println ("Total processed entries: " + entriesProcessed .longValue () + ", current entry: " + currentlyProcessedEntry );
723728 }, 5 , 1 , TimeUnit .MINUTES );
724729
725- List <String > requiresInit = new ArrayList <>(Arrays .asList (
726- "jdk.internal.vm.ci" , "jdk.graal.compiler" , "com.oracle.graal.graal_enterprise" ,
730+ var requiresInit = new HashSet <>(List .of ("jdk.internal.vm.ci" , "jdk.graal.compiler" , "com.oracle.graal.graal_enterprise" ,
727731 "org.graalvm.nativeimage" , "org.graalvm.truffle" , "org.graalvm.truffle.runtime" ,
728732 "org.graalvm.truffle.compiler" , "com.oracle.truffle.enterprise" , "org.graalvm.jniutils" ,
729733 "org.graalvm.nativebridge" ));
730734
731- Set <String > additionalSystemModules = upgradeAndSystemModuleFinder .findAll ().stream ().map (v -> v .descriptor ().name ()).collect (Collectors .toSet ());
735+ Set <String > additionalSystemModules = upgradeAndSystemModuleFinder .findAll ().stream ()
736+ .map (v -> v .descriptor ().name ())
737+ .collect (Collectors .toSet ());
732738 additionalSystemModules .retainAll (getJavaModuleNamesToInclude ());
733739 requiresInit .addAll (additionalSystemModules );
734740
741+ Set <String > explicitlyAddedModules = ModuleSupport .parseModuleSetModifierProperty (ModuleSupport .PROPERTY_IMAGE_EXPLICITLY_ADDED_MODULES );
742+
735743 for (ModuleReference moduleReference : upgradeAndSystemModuleFinder .findAll ()) {
736- if (requiresInit .contains (moduleReference .descriptor ().name ())) {
737- initModule (moduleReference );
744+ String moduleName = moduleReference .descriptor ().name ();
745+ boolean moduleRequiresInit = requiresInit .contains (moduleName );
746+ if (moduleRequiresInit || explicitlyAddedModules .contains (moduleName )) {
747+ initModule (moduleReference , moduleRequiresInit );
738748 }
739749 }
740750 for (ModuleReference moduleReference : modulepathModuleFinder .findAll ()) {
741- initModule (moduleReference );
751+ initModule (moduleReference , true );
742752 }
743753
744754 classpath ().parallelStream ().forEach (this ::loadClassesFromPath );
745755 } finally {
746756 scheduledExecutor .shutdown ();
747757 }
758+
759+ /* Verify all package inclusion requests were successful */
760+ for (String packageName : javaPackagesToInclude ) {
761+ if (!includedJavaPackages .contains (packageName )) {
762+ missingFromSetOfEntriesError (packageName , includedJavaPackages , "package" , IncludeAllFromPackage );
763+ }
764+ }
748765 }
749766
750- private void initModule (ModuleReference moduleReference ) {
767+ private void initModule (ModuleReference moduleReference , boolean moduleRequiresInit ) {
751768 String moduleReferenceLocation = moduleReference .location ().map (URI ::toString ).orElse ("UnknownModuleReferenceLocation" );
752769 currentlyProcessedEntry = moduleReferenceLocation ;
753770 Optional <Module > optionalModule = findModule (moduleReference .descriptor ().name ());
@@ -766,7 +783,7 @@ private void initModule(ModuleReference moduleReference) {
766783 String className = extractClassName (moduleResource , fileSystemSeparatorChar );
767784 if (className != null ) {
768785 currentlyProcessedEntry = moduleReferenceLocation + fileSystemSeparatorChar + moduleResource ;
769- executor .execute (() -> handleClassFileName (container , module , className , includeUnconditionally ));
786+ executor .execute (() -> handleClassFileName (container , module , className , includeUnconditionally , moduleRequiresInit ));
770787 }
771788 entriesProcessed .increment ();
772789 });
@@ -832,7 +849,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
832849 String className = extractClassName (fileName , fileSystemSeparatorChar );
833850 if (className != null ) {
834851 currentlyProcessedEntry = file .toUri ().toString ();
835- executor .execute (() -> handleClassFileName (container , null , className , includeUnconditionally ));
852+ executor .execute (() -> handleClassFileName (container , null , className , includeUnconditionally , true ));
836853 }
837854 entriesProcessed .increment ();
838855 return FileVisitResult .CONTINUE ;
@@ -916,24 +933,26 @@ private String extractClassName(String fileName, char fileSystemSeparatorChar) {
916933 return strippedClassFileName .equals ("module-info" ) ? null : strippedClassFileName .replace (fileSystemSeparatorChar , '.' );
917934 }
918935
919- private void handleClassFileName (URI container , Module module , String className , boolean includeUnconditionally ) {
920- synchronized (classes ) {
921- EconomicSet <String > classNames = classes .get (container );
922- if (classNames == null ) {
923- classNames = EconomicSet .create ();
924- classes .put (container , classNames );
936+ private void handleClassFileName (URI container , Module module , String className , boolean includeUnconditionally , boolean classRequiresInit ) {
937+ if (classRequiresInit ) {
938+ synchronized (classes ) {
939+ EconomicSet <String > classNames = classes .get (container );
940+ if (classNames == null ) {
941+ classNames = EconomicSet .create ();
942+ classes .put (container , classNames );
943+ }
944+ classNames .add (className );
925945 }
926- classNames . add ( className );
927- }
928- int packageSep = className . lastIndexOf ( '.' );
929- String packageName = packageSep > 0 ? className . substring ( 0 , packageSep ) : "" ;
930- synchronized ( packages ) {
931- EconomicSet < String > packageNames = packages . get ( container );
932- if ( packageNames == null ) {
933- packageNames = EconomicSet . create ();
934- packages . put ( container , packageNames );
946+ int packageSep = className . lastIndexOf ( '.' );
947+ String packageName = packageSep > 0 ? className . substring ( 0 , packageSep ) : "" ;
948+ synchronized ( packages ) {
949+ EconomicSet < String > packageNames = packages . get ( container ) ;
950+ if ( packageNames == null ) {
951+ packageNames = EconomicSet . create ( );
952+ packages . put ( container , packageNames );
953+ }
954+ packageNames . add ( packageName );
935955 }
936- packageNames .add (packageName );
937956 }
938957
939958 Class <?> clazz = null ;
@@ -945,10 +964,14 @@ private void handleClassFileName(URI container, Module module, String className,
945964 ImageClassLoader .handleClassLoadingError (t );
946965 }
947966 if (clazz != null ) {
948- if (includeUnconditionally ) {
967+ String packageName = clazz .getPackageName ();
968+ includedJavaPackages .add (packageName );
969+ if (includeUnconditionally || javaPackagesToInclude .contains (packageName )) {
949970 classesToIncludeUnconditionally .add (clazz );
950971 }
951- imageClassLoader .handleClass (clazz );
972+ if (classRequiresInit ) {
973+ imageClassLoader .handleClass (clazz );
974+ }
952975 }
953976 imageClassLoader .watchdog .recordActivity ();
954977 }
0 commit comments