History log of /libcore/luni/src/main/java/libcore/io/ClassPathURLStreamHandler.java
Revision Date Author Comments
fe872e2ac54d4032d7c16f3e01b114956cc5171c 09-Nov-2016 Neil Fuller <nfuller@google.com> Comment updates to make lifecycle concerns clearer

Fix / improve comments around JarFile sharing.

Bug: 32758243
Test: None - comment only change
Change-Id: Id264b4ca7d4f9116143760d4f9e4cd1f3c5ae6da
3c2b8eefe80d00b3ba54d27fed375886217e8778 21-Dec-2015 Paul Duffin <paulduffin@google.com> Encode entry name before creating URL

During retrieving a resource from the class path a URL is
constructed from the resource name. If the resource name
contains characters that are special in the file part of a URL,
e.g. # or ? then they need to be encoded (e.g. into %23 and %3f
respectively) before passing to the URL in order to ensure that
the name survives intact through to the JarURLConnection which
decodes the URL to extract the file part which it uses to scan
the JAR.

This ensures that the entry/resource name is encoded properly
and adds tests to verify that for resources whose names contain
either # or ?.

Bug: 26137833
Change-Id: I8f31c35e42c0070a0ee78e0cd58b67ebd001fffe
e8e4da2f84da30bbc11a63b7a87a153f62b1ce65 27-Nov-2015 Przemyslaw Szczepaniak <pszczepaniak@google.com> Remove StrictJarFile from ClassPathURLStreamHandler

StrictJarFile was moved from libcore to framework/base
(licensing reasons) and in no longer accessible in
the ClassPathURLStreamHandler. I replaced it using
JarFile class.

+ ZipFile compatibility fix, openjdk ZipFile#getInputStream
was not fine with directory entries without "/" suffix (returning null),
fixed a flag to deal with them like in previous impl.

Bug: 25337946
Change-Id: I9832b34664bd331a96cd06aabb4cbf834c58f208
ef411e4b8932bf0519ebf509817fac8506e44aa5 10-Sep-2015 Neil Fuller <nfuller@google.com> Fix JarURLConnection.getJarFile() caching behavior

Commits 05a5c2f and 2ce899f introduced alternative
handling for resources found in jars to reduce memory
usage.

There are a couple of issues fixed here to retain
behavior found on older Android releases (and still
implemented in libcore.net.url.JarURLConnecitonImpl):

1) There is an implicit contract on JarURLConnection that,
by default, any caller of JarURLConnection.getJarFile()
must not close the jar file. This is because
the default behavior is to use a VM-level cache of open
JarFile objects (see URLConnection.getUseCaches()).

In ClassPathURLStreamHandler, a JarFile was being
created on demand each time, regardless of the cache
setting. It was causing garbage collection warnings when
the caller abandoned it.

The exposure of the shared JarFile instance is
dangerous, but it is the way 3rd party code like ICU4J
assumes things work. It would be incorrect for the
caller to close the JarFile: to do so on earlier versions
of Android would cause problems for other users of the
classloader / jar.

2) There was an implicit contract on the InputStream
behavior when caching was switched off: closing the stream
should close the URLConnection and any associated JarFile.
This has now been implemented.

Bug: 20685844
Change-Id: I42e78fb74b40380fe1232e54876e75df1f434f1e
7cd7527ab01b87fced3855e5ed91dbaab708b017 09-Sep-2015 Neil Fuller <nfuller@google.com> Fix for boot classpath handling of directory entries

When finding resources, directory entries should be found
even if the trailing "/" is omitted.

Required by ICU4J when loading resources from jar files.
Thanks to Fredrik Roubert for the report.

Bug: 22527772
Change-Id: I2a1c20df98c7b284dab06214d308a9bfbd272824
384730cb57f41235f09829355d7ce67132625f7f 06-Jun-2015 Dmitriy Ivanov <dimitry@google.com> Fix lookup order when opening directly from APK

The order should be as follows:
1. Uncompressed native library dir (if any)
2. Directly from apk (<apk>!/lib/<abi>)
3. vendor/lib:/system/lib

Bug: http://b/21647354
Bug: http://b/21667767
Bug: http://b/21726698
Bug: http://b/8076853
Change-Id: I62cd76b7e4ae927d865d7d0ee81ceb91caa54e99
2ce899fcb81707dd5447a15c29c2c137697f2f5e 04-Jun-2015 Neil Fuller <nfuller@google.com> Revert "Revert "Modification to the way boot classpath resources are loaded""

This reverts commit 0c2e3c7fcb6754a2116c6226fe6480b3f6fa691f.

Change-Id: I37abbb83f6091f252c90645b8a088cf361fa6a7a
0c2e3c7fcb6754a2116c6226fe6480b3f6fa691f 03-Jun-2015 Neil Fuller <nfuller@google.com> Revert "Modification to the way boot classpath resources are loaded"

This reverts commit 05a5c2f89e12e27db69f24165a05bdfd0476c73a.

Change-Id: I07cc3841df40d20e2c09b0bf282bf213f422effe
05a5c2f89e12e27db69f24165a05bdfd0476c73a 19-May-2015 Neil Fuller <nfuller@google.com> Modification to the way boot classpath resources are loaded

VMClassLoader.getResource(), used by the Android boot classloader
was more expensive than it needed to be.

Context:

Checking each classpath entry for a resource involved opening a
zip file, checking for the resource and closing it again.

Because classloaders are arranged in a hierarchy, and parent
classloaders are checked first, this change should have a positive
performance impact for every call to ClassLoader.getResource(),
getResources() and getResourceAsStream(), regardless of the
classloader being used.

Details of change:

This change builds on an earlier commit for BaseDexClassLoader.
See commit 1a796cbc5dfb263511f2f4e5213adbc1d396a813 for the
earlier change. Unlike the BaseDexClassLoader change, we did
not have the zip file already open so this does impact the amount
of reported heap memory being used at rest in the zygote. It may
increase the amount of heap memory in use generally for jars
that have no resources because all jar files are opened, not
just the ones found to have requested resources. The heap memory
should consist of the entry metadata. The zip file itself is
mapped into non-heap/native memory.

Any resources loaded from the boot classloader previously
would have caused the JarURLConnection cache to hold the
associated zip file open anyway. See
https://code.google.com/p/android/issues/detail?id=60071 for
context. This change avoids the use of that cache for bootclass
path resources. Most other usages of jar: urls should now be
within the control of apps, and their can call setUseCache() to
prevent caching.

Performance:

Measured on a Nexus 5. All values in microseconds.

Benchmark (not real app):

GetBootResource_hit - looks for a resource known to be in the
boot classpath in core-libart: java/util/logging/logging.properties
GetBootResource_miss - looks for a resource known to be missing.

Before:
GetBootResource_hit 237
GetBootResource_miss 3034

After:
GetBootResource_hit 23.8
GetBootResource_miss 22.5

App (using vogar --mode activity):

Before:
Hit: 236-446
Miss: 3042-3555

After:
Hit: 65-180
Miss: 88-120

Memory usage:

The use of StrictJarFile keeps the memory usage down to low levels
levels: An initial implementation of this change that used JarFile
was showing up as expensive because the heap memory usage is
dependent on the number of entries in the jar. ext.jar was taking
up 275k due to a large number of resources associated with
libphonenumber. By using StrictJarFile, Java heap usage is now < 2k
per jar. The JarFile cost would previous have been paid anyway
if an app read a resource out of ext.jar (because of the
JarURLConnectionImpl cache) so this change should also produce savings
there. It does mean that we map all the class path jars into memory
natively, but the kernel should be managing that for us and sharing
the expense across all apps.

Given the runtime may be mapping the files for its own purposes
elsewhere the additional cost may even be nil.

Bug: https://code.google.com/p/android/issues/detail?id=60071
Bug: 20685844
Change-Id: Ic3dc4a655c46cc67bfe9b9e254036c6651869c92