Draw output of java output file type

Is it possible to get javac to output information about the types that it outputs for method calls?

For example, I want to know what is output for formal type T in a bar call .

 private static <T> void bar() { ... } public void foo() { bar(); } 

I studied javac -Xprint and friends, but can't find anything that reveals this level of detail.


EDIT Example. I did not want to state this initially, because it would complicate the answers. I'm primarily interested in getting debugging information from javac . In any case, it was a motivating example:

 public class Scratch { private static <T extends Throwable> void sneakyThrow(Throwable t) throws T { throw (T) t; // Warning: Type safety: Unchecked cast from Throwable to T } public void foo() { sneakyThrow(new Exception()); } } 

This compiles, but any reasonable decision regarding the actual type of T should give Throwable and require foo() throws Throwable . Eclipse seems to consider this a RuntimeException . I want to know what javac thinks. If this is a mistake in javac processing type parameters in the throws , the answer to this question would allow me to prove it.

+6
source share
2 answers

You can see in detail what javac displayed / resolved, etc. To do this, you need to use the hidden / unsupported / undocumented option: -XDverboseResolution. If someone wants to see all the information, then the transmitted value will be "all", as in: -XDverboseResolution = all. If you want to see only an instance of common methods, then the option: -XDverboseResolution = pending output. For the code in the original question, I get the following output:

: javac -XDverboseResolution=deferred-inference Scratch.java

output:

 Scratch.java:6: Note: Deferred instantiation of method <T>sneakyThrow(Throwable) sneakyThrow(new Exception()); ^ instantiated signature: (Throwable)void target-type: <none> where T is a type-variable: T extends Throwable declared in method <T>sneakyThrow(Throwable) Note: Scratch.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 

From this conclusion, you can conclude that T was created for Throwable.

Hope this is what you were looking for.

+2
source

What you are looking for is an erase type , not a type inference .

I do not know any option for javac that outputs type erase data.

Essentially, the compiler erases all type parameters to the smallest known type obtained from the type parameter:

  • <T> becomes Object
  • <T extends Number> becomes Number
  • <T extends Comparable<T>> becomes Comparable
  • <T extends Cloneable & Comparable<T>> becomes Cloneable
  • <T extends Object & Comparable<T>> becomes Object
  • <S, T extends S> becomes Object,Object

You can always check your .class file by calling javap -c <class_name>.class to see what the resulting bytecode is.

* NB Keep in mind that the compiler has various keys to save debugging information. See javac -g .

So, in terms of the experiment below, your code is slightly reworked (note type parameter in the class declaration and sneakyThrow(T t) throws T

 public class Scratch <T extends Throwable> { private static <T extends Throwable> void sneakyThrow(T t) throws T { throw (T) t; } public void foo() throws T { sneakyThrow((T) new Exception()); } } 

... and below is part of the output of javap -v -c Scratch.class after compilation with javac -g:none Scratch.java :

  Constant pool: #1 = Methodref #6.#19 // java/lang/Object."<init>":()V #2 = Class #20 // java/lang/Exception #3 = Methodref #2.#19 // java/lang/Exception."<init>":()V #4 = Methodref #5.#21 // Scratch.sneakyThrow:(Ljava/lang/Throwable;)V #5 = Class #22 // Scratch #6 = Class #23 // java/lang/Object #7 = Utf8 <init> #8 = Utf8 ()V #9 = Utf8 Code #10 = Utf8 sneakyThrow #11 = Utf8 (Ljava/lang/Throwable;)V #12 = Utf8 Exceptions #13 = Class #24 // java/lang/Throwable #14 = Utf8 Signature #15 = Utf8 <T:Ljava/lang/Throwable;>(TT;)V^TT; #16 = Utf8 foo #17 = Utf8 ()V^TT; #18 = Utf8 <T:Ljava/lang/Throwable;>Ljava/lang/Object; #19 = NameAndType #7:#8 // "<init>":()V #20 = Utf8 java/lang/Exception #21 = NameAndType #10:#11 // sneakyThrow:(Ljava/lang/Throwable;)V #22 = Utf8 Scratch #23 = Utf8 java/lang/Object #24 = Utf8 java/lang/Throwable public Scratch(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public void foo() throws T; Code: 0: new #2 // class java/lang/Exception 3: dup 4: invokespecial #3 // Method java/lang/Exception."<init>":()V 7: invokestatic #4 // Method sneakyThrow:(Ljava/lang/Throwable;)V 10: return } 

As you can see, Throwable is what type erasure is allowed.

+1
source

Source: https://habr.com/ru/post/971001/


All Articles