Page 1 of 5 123 ... LastLast
Results 1 to 20 of 82
Like Tree9Likes

Thread: Generics & 'Type Erasure': disingenuous documentation?

  1. #1
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Generics & 'Type Erasure': disingenuous documentation?

    Java 5 and onwards allows type variables and parametrized types to be used in declarations. 'Type Erasure' is a grandiose term describing a "process" whereby the compiler eliminates all references to these type variables and parameters in the generated byte code. The reason given is to make Java 5 and onwards compatible with earlier versions of Java, which do not support Generics.

    What I suspect is the case is that Generics has been added as incomplete, "design time only" support for parameterized types, which the compiler IGNORES at the point of actual generation of byte code -- hardly what I would call a "process of type erasure". I suspect that the compiler simply does nothing different, and generates the same byte code as the equivalent raw types. The only compiler difference is in its design time validation.

    Backward compatibility is a good reason for allowing aliasing of raw types with generic types. It is not a good reason for allowing heap pollution. Heap pollution causes pending runtime exceptions which should be trapped immediately. This suggests that parametrized type information is important at runtime, even when you require backward compatibility.

    Can anyone prove me wrong, perhaps by creating a concise example of a generic type that compiles into different byte code from its equivalent raw type?
    Last edited by 2by4; 12-11-2011 at 12:42 PM.

  2. #2
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,004
    Blog Entries
    7
    Rep Power
    20

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by 2by4 View Post
    Can anyone prove me wrong, perhaps by creating a concise example of a generic type that compiles into different byte code from its equivalent raw type?
    No we can't because the compiler doesn't generate any new code at all; Generics is a compile time thingy; even the runtime casts are still present, even if the compiler 'knows' that a generic type is of a matching concrete type. This is caused by the backwards compatibility b.t.w. Hava a look at the following snippet:

    Java Code:
    import java.util.ArrayList;
    import java.util.List;
    
    public class T {
    	public static void main(String[] args) {
    		List<String> list= new ArrayList<String>();
    		
    		list.add("foo");
    		System.out.println(list.get(0)+"bar");
    	}
    
    }
    The compiler 'knows' that the list will only contain objects of the type String, but still there's a runtime cast:

    Java Code:
    public class T extends java.lang.Object{
    public T();
      Code:
       0:   aload_0
       1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
       4:   return
    
    public static void main(java.lang.String[]);
      Code:
       0:   new     #16; //class java/util/ArrayList
       3:   dup
       4:   invokespecial   #18; //Method java/util/ArrayList."<init>":()V
       7:   astore_1
       8:   aload_1
       9:   ldc     #19; //String foo
       11:  invokeinterface #21,  2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
       16:  pop
       17:  getstatic       #27; //Field java/lang/System.out:Ljava/io/PrintStream;
       20:  new     #33; //class java/lang/StringBuilder
       23:  dup
       24:  aload_1
       25:  iconst_0
       26:  invokeinterface #35,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
       31:  checkcast       #39; //class java/lang/String
       34:  invokestatic    #41; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
       37:  invokespecial   #45; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
       40:  ldc     #48; //String bar
       42:  invokevirtual   #50; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       45:  invokevirtual   #54; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       48:  invokevirtual   #58; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       51:  return
    
    }
    See line #31; the cast wouldn't be needed if there were no 'raw' types. The only benefit is type safety during compile time and no explicit casts in the source code.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  3. #3
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Thanks JosAH. The presence of the cast adds weight to the argument that the compiler generates the same code as it does for a raw type. I just don't know why this isn't being stated upfront in documentation, but is being obfuscated in terms like "type erasure" which eventually seem to mean no more than "no change to the byte code generator".

    Did you see my point about heap pollution? Backward compatibility is not a reason for this "type erasure". Type is still needed at runtime for throwing exceptions at the correct point.

  4. #4
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,004
    Blog Entries
    7
    Rep Power
    20

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Yep, the generated code is the same as before generics saw the light. Those casts are still needed during runtime because of the 'backward compatibility'. I don't understand your remark on 'heap pollution'; a raw type can store any type of object and only if that cast fails, an Exception will be thrown. The cast can only fail if some 'backward compatible' code goofed ...

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  5. #5
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    JosAH

    My point about heap pollution is this. If a non-compatible type parameter is used for a generic type through being aliased with a raw type, the runtime allows heap pollution. The runtime will put the rogue object on the heap. It doesn't complain at that point! It should!

    It is only if you later assign the object to a "reifiable" type that it can give you a runtime exception.

    So, backward compatibility does not mean you should erase type information.

    Here is an example from the java trail..

    Java Code:
    List l = new ArrayList<Number>();
    List<String> ls = l;       // unchecked warning
    l.add(0, new Integer(42)); // another unchecked warning
    String s = ls.get(0);      // ClassCastException is thrown
    The runtime does not throw an exception on the add method. It defers it until the get.

  6. #6
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by 2by4 View Post
    The runtime does not throw an exception on the add method. It defers it until the get.
    I'm not sure what your issue is. It doesn't surprise me that Java doesn't complain about the add since the List variable, l, is not generic (and the compiler even warns you of this problem). If you made the variable generic, then you'd get a compile-time error from the code above and there wouldn't be any risk of "pollution".

  7. #7
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,004
    Blog Entries
    7
    Rep Power
    20

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    But that's all just because generics are a compiler issue, nothing on earth forbids anyone to use a List<T> as if it were a raw List (because of the 'backward compatibility' issue). I wish there would've been a compiler flag that forbids those 'raw' types and generates a hard error if a parameterized type were attempted to use as such. You're right, a 'non T' type can be stored in a List<T> without notice, or until it is attempted to use that 'non T' as if it were a T (hence the generated casts).

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  8. #8
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    But generics are not a "compiler issue". They've only implemented it as compiler issue and worded the documentation to make it sound OK.

    I do not believe it is correct for the runtime to place something on the heap and then LATER turn round and say, "oh, look what I've found on the heap! That shouldn't be there!"

    The reason for this problem is precisely because they have implemented generics as a compiler issue when it is more than that.

  9. #9
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by JosAH View Post
    You're right, a 'non T' type can be stored in a List<T> without notice, or until it is attempted to use that 'non T' as if it were a T (hence the generated casts).

    kind regards,

    Jos
    This is a usage issue, not a backward compatibility issue. Whenever would your new code want your legacy code to use List<T> in a non-T way?

  10. #10
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,004
    Blog Entries
    7
    Rep Power
    20

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by 2by4 View Post
    But generics are not a "compiler issue". They've only implemented it as compiler issue and worded the documentation to make it sound OK.

    I do not believe it is correct for the runtime to place something on the heap and then LATER turn round and say, "oh, look what I've found on the heap! That shouldn't be there!"

    The reason for this problem is precisely because they have implemented generics as a compiler issue when it is more than that.
    Ok, I reword that phrase: generics are a compile time issue in Java and hence its weakness. OTOH, when you want to go all the way, you end up with possible 'code bloat' as in C++'s templates; I guess the Java language designers wanted to avoid that.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  11. #11
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,004
    Blog Entries
    7
    Rep Power
    20

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by 2by4 View Post
    This is a usage issue, not a backward compatibility issue. Whenever would your new code want your legacy code to use List<T> in a non-T way?
    Now you're assuming a reasonable user; assumptions are always wrong ;-)

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  12. #12
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by JosAH View Post
    Ok, I reword that phrase: generics are a compile time issue in Java and hence its weakness. OTOH, when you want to go all the way, you end up with possible 'code bloat' as in C++'s templates; I guess the Java language designers wanted to avoid that.

    kind regards,

    Jos
    Then that is what the documentation should say ;-)

    It shouldn't obfuscate the "weakness" with excuses about backward compatibility. Backward compatibility does not force type erasure.

  13. #13
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by JosAH View Post
    Now you're assuming a reasonable user; assumptions are always wrong ;-)

    kind regards,

    Jos
    lol, no. You are assuming a reasonable user!

    I am saying trap the possible error. You seem to be saying it is not necessary!

  14. #14
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,004
    Blog Entries
    7
    Rep Power
    20

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by 2by4 View Post
    Then that is what the documentation should say ;-)

    It shouldn't obfuscate the "weakness" with excuses about backward compatibility. Backward compatibility does not force type erasure.
    I gave it some more thoughts, but, suppose the requirements were:

    a) old code should keep on compiling and
    b) old code should keep on running and
    c) generics are supposed to be a compile time thing only (a consequence of a) and b)?).

    then, 'type erasure' is the only solution ... of course that documentation only brags about it.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  15. #15
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by JosAH View Post
    c) generics are supposed to be a compile time thing only (a consequence of a) and b)?).

    then, 'type erasure' is the only solution ... of course that documentation only brags about it.

    kind regards,

    Jos
    But c) is not a consequence of a) and b). Nor is type erasure the only solution.

    Throwing a runtime exception at the point of heap pollution (which requires runtime generic type information) violates neither a) nor b).

    The reason it can't be done is because of type erasure, not backward compatibility!

    If I am using a parametrized type, it must be because I intend to access the object in a way that requires it to be of that type. Otherwise there would be no need to constrain it! Calling a legacy function that corrupts the parametrized type is misuse and should be flagged when it happens. Ideally, the error shouldn't be deferred to the point where the object is accessed.

    The idea that I could use a parametrized type for one part of its life cycle and then allow it to be something different in the latter part of its life cycle, is not what backward compatibility is supposed to support. Such a thing would be bad practice.

  16. #16
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by 2by4 View Post
    But c) is not a consequence of a) and b). Nor is type erasure the only solution.
    I don't know if it's the only solution, but it is the reasoning that the documentations give:

    "Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics."

    Source: Type Erasure

  17. #17
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by Fubarable View Post
    I don't know if it's the only solution, but it is the reasoning that the documentations give:

    "Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics."

    Source: Type Erasure
    Heap pollution is a result of the implemented solution and not the requirement.

    The documentation fails to mention that type erasure is a compromise that is more than just ensuring backward compatibility.

    I agree with JosAH that possible compiler and output bloat may be a factor.

    I think I was also a little hasty in saying type erasure is a simple matter of ignoring type information at generation time. I now recognise that, once you have decided to employ type erasure, deciding what the equivalent raw type would be is not necessarily a simple matter! With inheritance and correlated parametrization to consider, things could become complex and scenarios could arise that were not there before generics.
    Fubarable likes this.

  18. #18
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Here is another example of what I am finding disingenuous:

    Java interprets varargs as arrays. So taking the example from

    Java Trail - Potential Vulnerabilities of Varargs Methods with Non-Reifiable Formal Parameters

    Java Code:
      public static void faultyMethod(List<String>... l) {
        // Valid
        Object[] objectArray = l; 
        objectArray[0] = Arrays.asList(new Integer(42));
        // ClassCastException thrown here
        String s = l[0].get(0);
      }
    Method argument, "l", should first become List<String>[]

    The line labelled "Valid" should actually give an unchecked warning.

    Only at generation time should the <String> parameter be stripped, giving a List[].

    But what unfortunately seems to be happening is that the compiler does it all in one hit and immediately translates the varargs parameter l to List[] in anticipation of type erasure. That is why there is no warning, not because the line is valid.

    This is a glitch.

    Why have they labeled it "valid" and then pretended to explain it?

    If l were an explicit List<String>[], it would not anticipate type erasure. It would erase the type at the correct point and an unchecked error would be given!
    Last edited by 2by4; 12-13-2011 at 06:21 PM.

  19. #19
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    11,450
    Rep Power
    18

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    The line labelled valid will never give an unchecked warning, even if the parameter were a List<String>[].
    Java Code:
       private static void test(List<String>[] l) {
          Object[] o = l; // This is valid
    // do stuff
       }

  20. #20
    2by4 is offline Banned
    Join Date
    Dec 2011
    Posts
    143
    Rep Power
    0

    Default Re: Generics & 'Type Erasure': disingenuous documentation?

    Quote Originally Posted by Tolls View Post
    The line labelled valid will never give an unchecked warning, even if the parameter were a List<String>[].
    Java Code:
       private static void test(List<String>[] l) {
          Object[] o = l; // This is valid
    // do stuff
       }
    You are right. It does not give an unchecked warning. Question is, shouldn't it?

    I find this ambiguous..

    The method ArrayBuilder.faultyMethod shows why the compiler warns you about these kinds of methods. The first statement of this method assigns the varargs formal parameter l to the Object array objectArgs:

    Object[] objectArray = l;

    This statement can potentially introduce heap pollution. A value that does match the parameterized type of the varargs formal parameter l can be assigned to the variable objectArray, and thus can be assigned to l. However, the compiler does not generate an unchecked warning at this statement. The compiler has already generated a warning when it translated the varargs formal parameter List<String>... l to the formal parameter List[] l. This statement is valid; the variable l has the type List[], which is a subtype of Object[].

    Consequently, the compiler does not issue a warning or error if you assign a List object of any type to any array component of the objectArray array as shown by this statement:

    objectArray[0] = Arrays.asList(new Integer(42));
    So we have a "valid" statement which can potentially introduce heap pollution. What does "valid" mean then? Something is obviously skew-whiff.

    I mean, am I supposed to believe that creating a List<String>[] is essentially invalid, or is it an artifact of the Java Language? Is it not odd that the assignment statement, which is the clear candidate for incompatibility issues, is being called the valid statement? I would say that validity is being controlled by circumstance rather than essence.
    Last edited by 2by4; 12-14-2011 at 09:58 PM.

Page 1 of 5 123 ... LastLast

Similar Threads

  1. Type Erasure
    By Lil_Aziz1 in forum New To Java
    Replies: 3
    Last Post: 06-29-2010, 08:57 AM
  2. min / max and documentation
    By jon80 in forum New To Java
    Replies: 1
    Last Post: 04-20-2008, 12:37 PM
  3. documentation
    By mcal in forum New To Java
    Replies: 4
    Last Post: 02-07-2008, 06:20 AM
  4. Java Documentation
    By ravian in forum New To Java
    Replies: 4
    Last Post: 12-04-2007, 09:45 AM
  5. ArrayList<type> - Generics
    By Java Tip in forum Java Tip
    Replies: 0
    Last Post: 11-14-2007, 03:21 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •