review request for 7005608: diamond conversion of JCA and crypto providers

Stuart Marks stuart.marks at oracle.com
Thu Dec 23 12:40:22 PST 2010


On 12/22/10 6:17 PM, Brad Wetmore wrote:
> You need to update the Copyright updates on these files to include 2010.

Is this the standard, to update the copyright to the current year anytime the 
file is touched? If so, then yes, I can do this.

> Minor nit, can you add a space in line 221 between "BigInteger,BlindingParameters"

[and Max replied]
> I thought the formal style is no-space. At least in Map.java it's public interface Map<K,V>.

I'm not familiar with any formal style. The original Java code conventions doc 
[1] hasn't been updated since 1999 and so doesn't cover generics. I didn't see 
a more recent version.

The code base isn't consistent. I found about 3,000 uses of Map<...,...> in the 
JDK, and about 1,800 of those had a space after the comma and about 1,200 did 
not. To my eye it seems that single-letter type parameters such as Map<K,V> 
tend not to have the space whereas type parameters that name actual types, e.g. 
Map<String, Element> tend to have the space in there. However, the code base 
isn't consistent on that either.

I'm happy to change the code to <BigInteger, BlindingParameters> though.

[1] http://www.oracle.com/technetwork/java/codeconv-138413.html

> Not having a lot of experience yet with <>, the only ones I wasn't sure about
> were the ones in X509Factor.parseX509orPKCS7Cert. (line 415 & 425) I assume it
> just picks up the outer return type?

[and Max replied]
> I read the byte codes generated, and the parameters on lines 415 and 425 are not used. Maybe they are good for code readability.

Recall that generics are implemented by erasure, so no type parameters will end 
up in the bytecodes in any case. In fact, doing just the diamond conversion 
results in class files that are byte-for-byte identical to those from builds 
without the diamond conversion.

(The class files that result from building the code base with my webrev applied 
will in fact differ, though, because some of the lines have been joined where 
they're short enough. This will change the line number information in the class 
file, though it shouldn't change the actual bytecodes.)

But the issue is potentially significant in the source code. Here's the method 
in question, condensed for brevity. Lines changed by the diamond conversion are 
marked with **1** and so forth.

(Note also that X509CertImpl extends X509Certificate extends Certificate.)

     Collection<? extends Certificate> parse() {
         Collection<X509CertImpl> coll = new ArrayList<X509CertImpl>(); // **1**
         if (...)
             return new ArrayList<X509CertImpl>(0); // **2**
         try {
             X509Certificate[] certs = ...;
             if (...)
                 return Arrays.asList(certs);
             else
                 return new ArrayList<X509Certificate>(0); // **3**
         } catch {
             to coll, add instances of X509CertImpl
         }
         return coll;

At **1** if diamond were used, the type argument would clearly be X509CertImpl 
since that's right there in the declaration of the local variable.

At **2** and **3** (lines 415 and 425 in the file), when converted to use 
diamond, the type argument is inferred from the return type of the method. 
Since the return type is a bounded wildcard, the inferred type argument will be 
the upper bound, which is Certificate.

In these cases of diamond conversion, the inferred type will actually be 
different from what had been written before. Specifically, changing **2** to 
use diamond would be like changing it from

     return new ArrayList<X509CertImpl>(0);
to
     return new ArrayList<Certificate>(0);

and changing **3** to use diamond would be like changing it from

     return new ArrayList<X509Certificate>(0);
to
     return new ArrayList<Certificate>(0);

Now, what's the significance of this change? Would it be incorrect or 
misleading to use the diamond operator in the cases?

It's probably not incorrect from a type-safety point of view, since if it were, 
the compiler would issue an error or warning.

I guess the question is whether it's significant to the code in question 
whether in one case an ArrayList<X509CertImpl> is returned and in another case
ArrayList<X509Certificate> is returned, and also whether it's significant if 
these were both changed to ArrayList<Certificate>. To my eye, since the 
ArrayList is created empty and not otherwise used before it's returned, it's 
not significant. However, you guys (the maintainers of the code) are really the 
ones who need to decide.

s'marks








More information about the security-dev mailing list