RFR - 8132734: java.util.jar.* changes to support multi-release jar files

David M. Lloyd david.lloyd at redhat.com
Tue Oct 27 11:19:42 UTC 2015

FWIW I agree - it's just weird to have the behavior change after the 
fact like that.

On 10/26/2015 11:37 PM, Xueming Shen wrote:
> Hi Steve,
> I know I stared to sound like a broken record :-) But I would like to
> suggest the team one more
> time to reconsider the current decision of using the "set" methods to
> change the configuration
> setting/status of an existing JarFile to enable the multi-version support.
> public JarFile setVersioned(int version);
> public JarFile setRuntimeVersioned();
> The main concern here is the current approach basically transfers the
> JarFile from a read-only/
> immutable object with consistent behavior (to entry inquiry) to a
> mutable container of entries
> with possibility of inconsistent behavior. The newly introduced
> setVersioned/setRuntimeVersioned
> really have no way to guarantee A expected result from the updated
> version-enabled getEntry()
> method, as someone else might set an unexpected different "version"
> between your setting and
> getting, or even worse, in the middle of your entries() invocation, for
> example, in which you get
> part of your entries to version N and the rest to version M.
> So It might be desired to have the "versioned support" enabled in the
> constructor, so once you
> get that version enabled JarFile, it stays that way for its lifetime
> with consistent result for the
> entry inquiry, as the current API does.
> I do realize that there might be use case that the getEntry invoker
> might not have the access to
> the creation of the corresponding jar file (such as the use scenario in
> that JarURLConnection?), so
> you can't create a version-enabled JarFile at the very beginning via the
> constructor. But doesn't
> this also make my concern more real. If you don't have the control of
> the lifetime of that JarFile,
> you don't really have the control of who is setting or going to set the
> version of that mutable JarFile,
> right?
> An alternative might be to have change the
> setVersioned/setRuntimeVersioned() to
> public jarFile getVersioned(int version);
> public jarFile getRuntimeVersioned();
> to return a new copy of the existing JarFile with the desired verisoning
> support. Yes, it might be
> too heavy from performance perspective :-) and we might have to do some
> tricky stuff (it would
> be easier if ZipJarFile is interface ...) to have a light wrapper class
> to delegate everything to the
> real one.
> That said, I'm fine to be told "the pros and cons were considered,  and
> this is the best for the
> supported use scenario":-) In that case, it might deserve some wording
> in the spec notes to
> prepare the developer the possible unexpected.
> Thanks,
> Sherman
> On 10/26/15 10:26 AM, Steve Drach wrote:
>> Hi,
>> We’ve published another webrev for review.
>> Issue: https://bugs.openjdk.java.net/browse/JDK-8132734
>> JEP 238: https://bugs.openjdk.java.net/browse/JDK-8047305
>> Webrev: http://cr.openjdk.java.net/~psandoz/multiversion-jar/jar-webrev/
>> This one addresses the issues regarding CodeSigners, Certificates,
>> verification, and other security issues raised in the last round,
>> including whether third party verification is a supported use case.  I
>> also partially fixed a nitpick involving performance while searching
>> for versioned entries, by putting in a cache for previously searched
>> entries.  And I found a way around the issue with windows being unable
>> to delete jar files accessed through URL’s in one test.
>> Steve
>>> On Oct 21, 2015, at 12:54 AM, Wang Weijun <weijun.wang at oracle.com>
>>> wrote:
>>>> On Oct 21, 2015, at 3:17 PM, Xueming Shen <xueming.shen at oracle.com>
>>>> wrote:
>>>> We might want to bring in Max to take a look if what I said is
>>>> really a supported use scenario.
>>> I haven't read Steve's latest code change. I will read if you think
>>> it's necessary.
>>> First, I think we agree that the multi-release jar file feature is
>>> only making use of the existing jar file format and does not intend
>>> to introduce any change to its specification. This means a JarFile
>>> signed by one JDK release should be verified by another JDK release.
>>> Ok, the next question is, should it modify the JarFile API? I hope
>>> not, because the JarFile API is the single entry we access a JarFile
>>> when we want to sign or verify it. I hope there is a brand new API
>>> for a multi-versioned jar file, probably a child class of JarFile, so
>>> that no matter you call getJarEntry() or entries() on it, you always
>>> get the versioned one and the unrelated ones are completely invisible.
>>> If this is not OK, maybe we can rename the current JarFile to
>>> RawJarFile and name the new API JarFile. Signing and verification
>>> will work on RawJarFile.
>>> Not sure if it's easy.
>>> --Max
>>> On Oct 21, 2015, at 12:17 AM, Xueming Shen <xueming.shen at oracle.com>
>>> wrote:
>>> Hi Steve,
>>> The reifiedEntry() approach probably can help the default JarVerifier
>>> work as expected, but if I read the
>>> code correctly  I doubt you can get the expected CodSigner[] and
>>> Certificatte[] result from a "versioned"
>>> JarFileEntry, after having read all bytes from the input stream
>>> (obtained via jzf.getInputStream(JarFileEntry)),
>>> as the JarEntry spec suggests,. As we are passing the "reified" entry
>>> into the VerifierStream alone, without
>>> any reference to the original jar file entry.  It seems impossible
>>> for the original jar file entry can trace back to
>>> the corresponding certificates and code signers. This might be fixed
>>> by passing in the original entry together
>>> into the JarVerifier, but I doubt we might have a bigger issue here.
>>> I suspect with this approach an external
>>> verifier will have no easy way to verify the digit signature of the
>>> jar entry via java.security APIs. I would assume
>>> this is doable right now with current JarFile APIs, via a JarFile
>>> object, a Manifest and a target JarEntry. The external
>>> can get the signature via name -> manifest->attributes->signature
>>> (basically just consider to move the
>>> JarVerifier and couple sun.security.util classes out and use it as
>>> user code)... but with this implementation
>>> the name now  is the root entry, but the bytes you can read from the
>>> stream is from the versioned one.
>>> We might want to bring in Max to take a look if what I said is really
>>> a supported use scenario. I might be
>>> wrong, not a security expert :-)
>>> Btw, for a "normal" JarEntry/ZipEntry (not a JarFileEntry), shouldn't
>>> the getInputStream(ze) simply return
>>> the stream for the root entry? The current implementation of
>>> getJarEntry(ze) does not seem right, as it
>>> returns a "versioned" JarFileEntry. I don't think you want to pass
>>> this one into VerifierStream directly,
>>> right? Again, I think it might be desired (at least the spec is not
>>> updated to say anything about "version")
>>> to simply return the input stream for the root entry.
>>> One more "nitpick". searchForVersionedEntry() now lookups the
>>> versioned candidate via super.getEntry()
>>> from version to BASE_VERSION, if the version is the latest version 9,
>>> the base is 0, we are basically doing
>>> this search for each non-versioned-entry inside this
>>> multi-release-jar file 9 times everytime when the entry
>>> is asked. In worse case scenario, a multi-release-jar, with huge
>>> number of entries with a small portion are
>>> versioned to 9, and you are iterating it via "entries". Each lookup
>>> might be cheap, but it might be worth
>>> considering adding some optimization.
>>> Best,
>>> Sherman


More information about the core-libs-dev mailing list