RFR (S) 8151223: String concatenation fails with implicit toString() on package-private class
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Mar 7 19:19:11 UTC 2016
Hi Alexm
thanks for the patch; the idea is generally sound - I have few questions
about the implementation of the 'sharpestAccessible' method when it
comes to some javac quirks:
* note that when you recur on supertypes, you will end up with
Type.noType, a type whose tag is NONE. In other words, supertype(Object)
== Type.noType. This means that the current patch is (i) risking a bit
when calling isAccessible on Type.noType - I'm not 100% sure if that's
supported - might just work accidentallly and (ii) the subsequent test:
if (!sharpestClass.equals(syms.objectType)) {
+ return sharpestClass;
+ }
Is redundant (and wrong) - in other words, you will always exit the loop
with some type that is != Object (I think), which makes the interface
part useless.
* when it comes to interface sharpening, your code prefers D to B when
calling the sharpening routine on InaccessibleA:
class InaccessibleA extends InaccessibeB implements InaccessibleC { }
class InaccessibleB implements B { }
interface InaccessibleC implements InaccessibleD { }
interface InaccessibleD extends D { }
interface B { }
interface D { }
In other words, the routine does a depth-first search on superclasses,
followed by a depth-first search on interfaces. Would it make sense to
have a routine in which all direct supertypes are treated equally? I.e.
you look for an accessible supertype in the list of direct supertypes
(Types.directSupertypes) - if one is found you return it, if none is
found you repeat the check on the superclass.
* I'm not sure what happens when the input of the routine is not a
classtype? I.e. an array or a type-var? Now, it seems like type-vars are
probably erased before this point (or you'd have issue in the current
impl too) - but arrays can definitively come up. Now, testing an array
type doesn't make a lot of sense, since the array class is fictional;
and array supertypes are not meaningful - i.e. Serializable and
Cloneable - you don't want to end up with such types in the indy. I
think array types should be special cased, so that the sharpening logic
works on the element type. This means that this routine probably needs
to become a type visitor (Types.SimpleTypeVisitor) - which has different
behaviours for different type shapes.
The rest looks good.
Maurizio
On 07/03/16 18:46, Aleksey Shipilev wrote:
> Hi,
>
> There seems to be a corner case in our current String concatenation
> handling: we are recording the exact argument types to call
> StringConcatFactory with, to allow JDK to use that information for
> optimization. This works well, until we meet a private class. Then, we
> get an IllegalAccessError while trying to execute a bootstrap method
> referencing an inaccessible class:
> https://bugs.openjdk.java.net/browse/JDK-8151223
>
> This does not happen with "old" concat flavor, because we are calling
> StringBuilder.append(Object) there, which does not leak away the private
> type.
>
> Luckily, we are not mandated to always call StringConcatFactory with an
> exact type. We can detect inaccessible classes during compilation, and
> use the closest accessible super-type instead. We could just strip to
> java.lang.Object in those cases, but it seems better to sharpen the type
> to the first accessible/non-ambiguous class/interface up the hierarchy.
>
> Webrev:
> http://cr.openjdk.java.net/~shade/8151223/webrev.01
>
> Testing: failing test, new regression test; JDK java/lang/String;
> Langtools com/,jdk/,tools/
>
> Thanks,
> -Aleksey
>
More information about the compiler-dev
mailing list