Update `JarURLConnection` to ensure that when connections are opened
a new copy of the JarFile is provided.
Prior to this commit, a single `JarFile` instance was shared which meant
that it could be accidental closed if accessed via
`JarURLConnection.getJarFile()`. If the underlying jar file is closed
then it's possible for a `NoClassDefFoundError` to be thrown if running
on JDK 11 with an active `SecurityManager`.
Closes gh-17796
ExecutableArchiveLauncher.createClassLoader(Iterator) calls
createClassLoader(URL) method with 'super'. This means overriding
createClassLoader(URL) is not possible without also overriding
createClassLoader(Iterator). The switch to 'this' enables that.
See gh-20851
Update the Maven plugin so that layered jars now use the regular "flat"
format. The layers.idx file now describes which layer each file should
be placed.
See gh-20813
Co-authored-by: Phillip Webb <pwebb@pivotal.io>
Update `LaunchedURLClassLoader` to ensure that the `JarModeLauncher`
is created in the correct classloader.
Prior to this commit the launcher was created by the application
classloader and did not have access to any of the required
`org.springframework` classes.
See gh-19848
Update all dependencies declarations to use the form `scope(reference)`
rather than `scope reference`.
Prior to this commit we declared dependencies without parentheses unless
we were forced to add them due to an `exclude`.
Replace Gradle single quote strings with the double quote form
whenever possible. The change helps to being consistency to the
dependencies section where mostly single quotes were used, but
occasionally double quotes were required due to `${}` references.
Fix a bug in `ExplodedURLClassLoader` and merge the code into the
existing `LaunchedURLClassLoader` class. Also polish a few method
names relating to layer support.
See gh-19848
See gh-19767
Update the `Launcher` class to allow a packaged jar to be launched in
a different mode. The launcher now checks for a `jarmode` property and
attempts to find a `JarMode` implementation using the standard
`spring.factories` mechanism.
Closes gh-19848
Support an alternative fat jar format that is more amenable to Docker
image layers.
The new format arranges files in the following structure:
BOOT-INF/
layers/
<layer-name #1>
/classes
/lib
<layer-name #2>
/classes
/lib
The `BOOT-INF/layers.idx` file provides the names of the layers and the
order in which they should be added (starting with the least changed).
The `JarLauncher` class can load layered jars in both fat and exploded
forms.
Closes gh-19767
Co-authored-by: Phillip Webb <pwebb@pivotal.io>
Update the `Repackager` class so that an additional `classpath.idx` file
is written into the jar that provides the original order of the
classpath. The `JarLauncher` class now uses this file when running as
an exploded archive to ensure that the classpath order is the same as
when running from the far jar.
Closes gh-9128
Co-authored-by: Phillip Webb <pwebb@pivotal.io>
The JarFile was not being closed which linked a file handle and caused
a test failure on Windows.
The local variable has been renamed as, when declared in a
try-with-resources, Checkstyle was confused by the shadowing of the
jarFile field and required references to jarFile within the try-block
the be prefixed with this.
See gh-19595
This paves the way for publishing Gradle module metadata once the
problem caused by snapshot versions and our two-step publication
process has been addressed.
See gh-19609
This reverts commit b34a311d02 as,
having disabled the publishing of Gradle's module metadata (4f75ab5),
the changes are no longer needed.
See gh-19609
Previously, enforcedPlatform dependencies were using to pull in the
constraints defined in spring-boot-dependencies and
spring-boot-parent and applied them strictly so that the constrained
version had to be used. This worked as intended in Spring Boot's own
build but incorrectly enforced those same strict version requirements
on external consumers of Spring Boot's modules.
This commit reworks how Spring Boot defines its internal dependency
management so that platform dependencies are exposed to external
consumers while enforced platform dependencies are using internally.
See gh-19609
- Previously, we would create a JarFileArchive for all nested jars.
This was an additional overhead. We only need to create a JarFileArchive
for jars that can have nested jars in them. For all other jars we only need
the URL to build the classpath.
- While iterating over nested entries in the exploded jar, we only need to
look at BOOT-INF and we can skip any entry that does not match that.
Closes gh-16655
Co-authored-by: Phillip Webb <pwebb@pivotal.io>
Previously, Maven's default behaviour was relied up which resulted
in the artifact ID being appended to each URL as it was inherited.
This behaviour can only be disabled in Maven 3.6 and later, a version
that we cannot use due to an incompatibility with the Flatten Plugin.
This commit works around Maven's default behaviour by defining
properties for the SCM URL, connection, and developer connection and
then explicitly defining the settings in each pom using these
properties. The explicit definition of the properties in each pom
prevents them being inherited from the parent, thereby disabling the
unwanted appending of the artifact ID to the URL.
Fixes gh-18328
Previously, calling getComment() on a nested jar file would result
in the outer jar file's comment being returned.
This commit updates the loader's JarFile to read the file's comment
from the central directory end record and return it from getComment().
Fixes gh-18128
Apply checkstyle rule to ensure that private and package private
classes do not have unnecessary public methods. Test classes have
also been unified as much as possible to use default scoped
inner-classes.
Closes gh-7316
Previously, a regular expression of /./ was used to replace /./ with
/. The '.'' in the expression matches any single character so the
replacement was more broadly applicable than it should have been. For
example, /a/ would be replaced with /.
This commit uses Pattern.LITERAL to compile the regular expression
from the CURRENT_DIR (/./) contant. This allows the constant to be
used to check for occurances of /./ in the string before attempting
replacement, while also ensuring that the '.' is treated literally.
Closes gh-17341
Since the move to JUnit 5, a number of tests were failing on Windows.
The majority were failing due to open file handles preventing the
clean up of the tests' temporary directory. This commit addresses
these failures by updating the tests to close JarFiles, InputStreams,
OutputStreams etc.
A change has also been made to CachingOperationInvokerTests to make
a flakey test more robust. Due to System.currentTimeMillis() being
less precise on Windows than it is on *nix platforms, the test could
fail as it would not sleep for long enough for the TTL period to have
expired.
This commit avoids calling the underlying ZipEntry.setExtra() method
that is not very inline friendly in cases where there is no extra
information to be set.
See gh-16620
Previously, an entry’s potentially aliased name would be used when
checking that it has a particular name. The alias would always be
applied, irrespective of the name in the header. As a result, when
there was a clashing hash and an entry with a particular index did
not have the expected name, this would be concealed by the alias
being applied and the name check being done with the alias.
This commit reworks JarEntry to store the name in its header in
addition to its alias, if any. When checking that the entry has the
expected name, the unaliased name is passed in and the entry compares
it with the name from the header rather than the alias.
Closes gh-15981
Update the JAR `Hander` so that URL `startsWith` checks produce less
garbage. Comparisons are now performed first on the `path` rather than
the full `toString`. URL `toString` operations produce quite a lot of
garbage since a `StringBuilder` is always used.
In addition, we now also cache the JarFile URL toString to save repeated
calculation.
Closes gh-14561
Previously, the underlying RandomAccessDataFile was not closed when
the JarFile that was using it was closed. This causes a problem on
Windows as the open file handle prevents the file from being deleted.
This commit updates JarFile to close the underlying
RandomAccessDataFile when it is closed and has a JarFileType of
DIRECT.
Previously, when accessing the manifest of a jar file that maps to a
nested directory (BOOT-INF/classes) a new JarFile was created from the
root jar file, the manifest was retrieved, and the new JarFile was
closed. This could lead to the underlying RandomAccessDataFile being
closed while it was still in use.
This commit improves JarFile to retrieve the manifest from the
existing outer JarFile, thereby avoiding the need to create and close
a new JarFile.
Unfortunately, PropertiesLauncher creates a number of scenarios where
a JarFile with a type of direct is closed while it’s still being used.
To accommodate this behaviour, RandomAccessDataFile has been updated
so that it can re-open the underlying RandomAccessFile if it is used
after it has been closed.
Closes gh-12296
Previously, working with a JarFile created a large amount of garbage
that was allocated on the thread local allocation buffer (TLAB).
The TLAB allocations made a significant contribution to GC pressure
and slowed down startup. This commit reduces the amount of garbage
by making a number of changes.
Reading from a RandomAccessDataFile has been reworked to avoid
creating new RandomAccessFile instances. A single RandomAccessFile
is now created for an entire jar file and it is used to read data from
anywhere in that jar file, including entries in nested jar files. To
ensure that reads remain thread-safe, a lock is taken on the
RandomAccessFile that is shared by all RandomAccessDataFile instances
that are provided access to (portions of) the same jar file.
Reading all of the bytes from a RandomAccessData has been reworked to
avoid the use of an InputStream that was created, used to read the
data, and then thrown away. In place of the InputStream-based
mechanism a method has been introduced that returns all of the
RandomAccessData as a byte[]. Building on this change, a method has
also been introduced to read a portion of a RandomAccessData as a
byte[]. This avoids the need to create a new RandomAccessData
subsection where the subsection was only used to read its entire
contents and then thrown away.
Decoding of an MS-DOS datetime has been reworked to use LocalDataTime
rather than GregorianCalendar. The former produces less garbage than
the latter.
Closes gh-12226
Update the `LaunchedURLClassLoader` used for fat jar support so that
each iteration on a `findResources` result also allows for fast
exceptions.
Fixes gh-11406
Refactor fat jar loader classes so that less `char[]` instances are
created. This is primarily achieved by adding a new `StringSequence`
class that can chop up Strings without needing to copy the underlying
array. Since Java 8, calls to `String.subString(...)` always copy the
underlying char array. For many of the operations that we need, this
is unnecessary.
Fixes gh-11405