JDK-8150745 : race between module definition with a package and loading a class in the same package
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Not an Issue
  • Submitted: 2016-02-26
  • Updated: 2016-12-12
  • Resolved: 2016-12-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Resolved
Related Reports
Relates :  
Description
Alan spotted this potential issue:

Also, we need to think about the race where one thread attempts to define a module containing a package at around the same time that another thread is loading a class (the first class) in the same package/loader. The JPLIS agent will be triggered by the later but, I think, random as to whether it will invoke the ClassFileTransformer with the loader's unnamed module or the newly defined named module. I don't think this is a concern for the JVM_ entry point, but I think will surface once we start to build on it. 
. . .
Back to the race issue that I mentioned, maybe we can create a separate issue for that. I suspect this will require a few changes in the runtime to eagerly record.

Comments
yes, you're right.
12-12-2016

Why is this closed as "fixed"? Shouldn't it be closed as "not a bug"?
12-12-2016

After further discussions it's been determined that the race condition does not exist. In the first case above, the attempt to define a module with an existing package should throw an exception. Alternatively, we could let the last module that defined the package win, but this would be a bit chaotic because the package's readability would change as it got moved from module to module. It would also lead to the case #1 race condition. Letting the first defined module win and silently ignoring the duplicated package in subsequent defined modules would prevent users from knowing that they mistakenly tried to put the same package in different modules. Throwing an exception when defining a module containing a package that is already In the unnamed module is a good way to inform users about the problem.
12-12-2016

[ ~harold ] Is it Ok to fail with a IllegalArgumentException as a result of a race in case #1?
07-12-2016

If the module is defined before the class is loaded, then GetModuleByPackageName will return the named module, even if the VM initially doesn't find the module. Here's how the code that determines a class's module is implemented: 1: if package is not in a module { 2: lock Module_lock; 3: check again if package is in a module, and if so, return it; 4: else put package in unnamed module; 5: } So, if the package's module got defined after the initial check at line 1, but before locking Module_lock, the second check at line 3 will find and return the newly created named module. Note that if the check at line 3 does not find a module then the package will be put in the unnamed module and will remain there, even if, later on, someone tries to put that package in a named module.
17-06-2016

[ To Harold: ] The synchronization you described looks enough to prevent this race condition. My understanding is that this bug was created as a placeholder as Alan had its concern about a potential race. We probably can close it as "Not a bug". One more thing to check is the point when the CFLH event is posted in the class loading sequence. The question is if the class's package has been already recorded at the CFLH post time. We need the GetModuleByPackageName to return a named module if the class belongs to it. But if the package has not been registered yet at CFLH post time then the GetModuleByPackageName will return the unnamed module.
17-06-2016

When the VM defines a module it locks the Module lock until the module and its PackageEntries are created. When the VM loads a class it tries to get a PackageEntry for that class's package. If no PackageEntry exists, then the VM locks the Module lock when creating a PackageEntry. After locking the Module lock, the PackageEntry creation code will check again to see if the desired PackageEntry exists. If so, then it just returns it. Does this synchronization around the the Module lock prevent the race condition?
16-06-2016