title: how to understand -keepattributes Signature in Proguard?
body: <p>I don't understand how to use this <code>-keepattributes Signature</code> in Proguard file?
  The Proguard Manual tip is "The "Signature" attribute is required to be able to access generic types when compiling in JDK 5.0 and higher."</p>
  
  <p>I use this attritube test and this is code and progurad code? </p>
  
  <p>Souce Code</p>
  
  <p>```</p>
  
  <pre><code>package com.example.pc.myapplication.utils;
  
  import android.support.annotation.Keep;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  public class GenericTypeTest {
  
    public static void test() {
      Student t = beanRepository();
  
      GenericInterface&lt;Student&gt; genericInterface = new GenericInterface&lt;Student&gt;() {
        @Override public void print(Student o) {
          System.out.println(o.toString());
        }
      };
      System.out.println(genericInterface);
      genericInterface.print(t);
  
      GenericClass&lt;Student&gt; genericClass = new GenericClass&lt;&gt;();
      System.out.println(genericClass);
      genericClass.print(t);
  
      genericMethod(t);
  
      genericCollection();
    }
  
    public static void genericCollection() {
      List&lt;Student&gt; students = listsRepository();
      if (students != null &amp;&amp; students.size() &gt; 0) {
        for (Student item : students) {
          System.out.println(item);
        }
      }
  
      HashMap&lt;Integer, Student&gt; hashMap = mapsRepository();
      if (hashMap != null &amp;&amp; hashMap.size() &gt; 0) {
        for (Map.Entry&lt;Integer, Student&gt; item : hashMap.entrySet()) {
          Integer key = item.getKey();
          Student value = item.getValue();
          System.out.println(key + ";" + value);
        }
      }
    }
  
    public interface GenericInterface&lt;T&gt; {
      void print(T t);
    }
  
    public static class GenericClass&lt;T&gt; {
      public void print(T t) {
        System.out.println(t);
      }
    }
  
    public static &lt;T&gt; void genericMethod(T t) {
      System.out.println(t);
    }
  
    public static Student beanRepository() {
      Student student = new Student();
      student.setName("Hello");
      student.setAge(30);
      student.setSex(false);
      return student;
    }
  
    public static List&lt;Student&gt; listsRepository() {
      ArrayList&lt;Student&gt; students = new ArrayList&lt;&gt;();
      for (int i = 0; i &lt; 50; i++) {
        Student student = new Student();
        student.setName("Index" + i);
        student.setAge(i + 30);
        student.setSex(false);
        students.add(student);
      }
      return students;
    }
  
    public static HashMap&lt;Integer, Student&gt; mapsRepository() {
      HashMap&lt;Integer, Student&gt; hashMap = new HashMap&lt;&gt;();
      for (int i = 0; i &lt; 50; i++) {
        Student student = new Student();
        student.setName("Index" + i);
        student.setAge(i + 30);
        student.setSex(false);
        hashMap.put(i, student);
      }
      return hashMap;
    }
  
    @Keep public static class Student {
      private String name;
      private int age;
      private boolean sex;
  
      public String getName() {
        return name;
      }
  
      public void setName(String name) {
        this.name = name;
      }
  
      public int getAge() {
        return age;
      }
  
      public void setAge(int age) {
        this.age = age;
      }
  
      public boolean isSex() {
        return sex;
      }
  
      public void setSex(boolean sex) {
        this.sex = sex;
      }
  
      @Override public String toString() {
        return "Student{" + "name='" + name + '\'' + ", age=" + age + ", sex=" + sex + '}';
      }
    }
  }
  </code></pre>
  
  <p>```</p>
  
  <p>dont add attribetu generated code</p>
  
  <p>```</p>
  
  <pre><code>package com.example.pc.myapplication.utils;
  
  import android.support.annotation.Keep;
  import java.io.PrintStream;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map.Entry;
  import java.util.Set;
  
  public class GenericTypeTest
  {
    public static void a()
    {
      Student localStudent = c();
      Object localObject = new b()
      {
        public void a(GenericTypeTest.Student paramAnonymousStudent)
        {
          System.out.println(paramAnonymousStudent.toString());
        }
      };
      System.out.println(localObject);
      ((b)localObject).a(localStudent);
      localObject = new a();
      System.out.println(localObject);
      ((a)localObject).a(localStudent);
      a(localStudent);
      b();
    }
  
    public static &lt;T&gt; void a(T paramT)
    {
      System.out.println(paramT);
    }
  
    public static void b()
    {
      Object localObject1 = d();
      Object localObject2;
      if ((localObject1 != null) &amp;&amp; (((List)localObject1).size() &gt; 0))
      {
        localObject1 = ((List)localObject1).iterator();
        while (((Iterator)localObject1).hasNext())
        {
          localObject2 = (Student)((Iterator)localObject1).next();
          System.out.println(localObject2);
        }
      }
      localObject1 = e();
      if ((localObject1 != null) &amp;&amp; (((HashMap)localObject1).size() &gt; 0))
      {
        localObject1 = ((HashMap)localObject1).entrySet().iterator();
        while (((Iterator)localObject1).hasNext())
        {
          Object localObject3 = (Map.Entry)((Iterator)localObject1).next();
          localObject2 = (Integer)((Map.Entry)localObject3).getKey();
          localObject3 = (Student)((Map.Entry)localObject3).getValue();
          System.out.println(localObject2 + ";" + localObject3);
        }
      }
    }
  
    public static Student c()
    {
      Student localStudent = new Student();
      localStudent.setName("Hello");
      localStudent.setAge(30);
      localStudent.setSex(false);
      return localStudent;
    }
  
    public static List&lt;Student&gt; d()
    {
      ArrayList localArrayList = new ArrayList();
      int i = 0;
      while (i &lt; 50)
      {
        Student localStudent = new Student();
        localStudent.setName("Index" + i);
        localStudent.setAge(i + 30);
        localStudent.setSex(false);
        localArrayList.add(localStudent);
        i += 1;
      }
      return localArrayList;
    }
  
    public static HashMap&lt;Integer, Student&gt; e()
    {
      HashMap localHashMap = new HashMap();
      int i = 0;
      while (i &lt; 50)
      {
        Student localStudent = new Student();
        localStudent.setName("Index" + i);
        localStudent.setAge(i + 30);
        localStudent.setSex(false);
        localHashMap.put(Integer.valueOf(i), localStudent);
        i += 1;
      }
      return localHashMap;
    }
  
    @Keep
    public static class Student
    {
      private int age;
      private String name;
      private boolean sex;
  
      public int getAge()
      {
        return this.age;
      }
  
      public String getName()
      {
        return this.name;
      }
  
      public boolean isSex()
      {
        return this.sex;
      }
  
      public void setAge(int paramInt)
      {
        this.age = paramInt;
      }
  
      public void setName(String paramString)
      {
        this.name = paramString;
      }
  
      public void setSex(boolean paramBoolean)
      {
        this.sex = paramBoolean;
      }
  
      public String toString()
      {
        return "Student{name='" + this.name + '\'' + ", age=" + this.age + ", sex=" + this.sex + '}';
      }
    }
  
    public static class a&lt;T&gt;
    {
      public void a(T paramT)
      {
        System.out.println(paramT);
      }
    }
  
    public static abstract interface b&lt;T&gt;
    {
      public abstract void a(T paramT);
    }
  }
  </code></pre>
  
  <p>```</p>
  
  <p>add <code>-keepattributes Signature</code> generated code
  ```</p>
  
  <pre><code>package com.example.pc.myapplication.utils;
  
  import android.support.annotation.Keep;
  import java.io.PrintStream;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map.Entry;
  import java.util.Set;
  
  public class GenericTypeTest
  {
    public static void a()
    {
      Student localStudent = c();
      Object localObject = new b()
      {
        public void a(GenericTypeTest.Student paramAnonymousStudent)
        {
          System.out.println(paramAnonymousStudent.toString());
        }
      };
      System.out.println(localObject);
      ((b)localObject).a(localStudent);
      localObject = new a();
      System.out.println(localObject);
      ((a)localObject).a(localStudent);
      a(localStudent);
      b();
    }
  
    public static &lt;T&gt; void a(T paramT)
    {
      System.out.println(paramT);
    }
  
    public static void b()
    {
      Object localObject1 = d();
      Object localObject2;
      if ((localObject1 != null) &amp;&amp; (((List)localObject1).size() &gt; 0))
      {
        localObject1 = ((List)localObject1).iterator();
        while (((Iterator)localObject1).hasNext())
        {
          localObject2 = (Student)((Iterator)localObject1).next();
          System.out.println(localObject2);
        }
      }
      localObject1 = e();
      if ((localObject1 != null) &amp;&amp; (((HashMap)localObject1).size() &gt; 0))
      {
        localObject1 = ((HashMap)localObject1).entrySet().iterator();
        while (((Iterator)localObject1).hasNext())
        {
          Object localObject3 = (Map.Entry)((Iterator)localObject1).next();
          localObject2 = (Integer)((Map.Entry)localObject3).getKey();
          localObject3 = (Student)((Map.Entry)localObject3).getValue();
          System.out.println(localObject2 + ";" + localObject3);
        }
      }
    }
  
    public static Student c()
    {
      Student localStudent = new Student();
      localStudent.setName("Hello");
      localStudent.setAge(30);
      localStudent.setSex(false);
      return localStudent;
    }
  
    public static List&lt;Student&gt; d()
    {
      ArrayList localArrayList = new ArrayList();
      int i = 0;
      while (i &lt; 50)
      {
        Student localStudent = new Student();
        localStudent.setName("Index" + i);
        localStudent.setAge(i + 30);
        localStudent.setSex(false);
        localArrayList.add(localStudent);
        i += 1;
      }
      return localArrayList;
    }
  
    public static HashMap&lt;Integer, Student&gt; e()
    {
      HashMap localHashMap = new HashMap();
      int i = 0;
      while (i &lt; 50)
      {
        Student localStudent = new Student();
        localStudent.setName("Index" + i);
        localStudent.setAge(i + 30);
        localStudent.setSex(false);
        localHashMap.put(Integer.valueOf(i), localStudent);
        i += 1;
      }
      return localHashMap;
    }
  
    @Keep
    public static class Student
    {
      private int age;
      private String name;
      private boolean sex;
  
      public int getAge()
      {
        return this.age;
      }
  
      public String getName()
      {
        return this.name;
      }
  
      public boolean isSex()
      {
        return this.sex;
      }
  
      public void setAge(int paramInt)
      {
        this.age = paramInt;
      }
  
      public void setName(String paramString)
      {
        this.name = paramString;
      }
  
      public void setSex(boolean paramBoolean)
      {
        this.sex = paramBoolean;
      }
  
      public String toString()
      {
        return "Student{name='" + this.name + '\'' + ", age=" + this.age + ", sex=" + this.sex + '}';
      }
    }
  
    public static class a&lt;T&gt;
    {
      public void a(T paramT)
      {
        System.out.println(paramT);
      }
    }
  
    public static abstract interface b&lt;T&gt;
    {
      public abstract void a(T paramT);
    }
  }
  </code></pre>
  
  <p>```</p>
  
  <p>Look the code is same, why use this <code>-keepattributes Signature</code>.</p>
  
  <p>And this is the whole proguard file:</p>
  
  <p>```
      # Add project specific ProGuard rules here.
      # By default, the flags in this file are appended to flags specified
      # in D:\develop\AndroidSDK/tools/proguard/proguard-android.txt
      # You can edit the include path and order by changing the proguardFiles
      # directive in build.gradle.
      #
      # For more details, see
      #   <a href="http://developer.android.com/guide/developing/tools/proguard.html" rel="nofollow noreferrer">http://developer.android.com/guide/developing/tools/proguard.html</a></p>
  
  <pre><code># Add any project specific keep options here:
  
  # If your project uses WebView with JS, uncomment the following
  # and specify the fully qualified class name to the JavaScript interface
  # class:
  -keepclassmembers class fqcn.of.javascript.interface.for.webview {
     public *;
  }
  
  # Uncomment this to preserve the line number information for
  # debugging stack traces.
  -keepattributes SourceFile,LineNumberTable
  
  # If you keep the line number information, uncomment this to
  # hide the original source file name.
  -renamesourcefileattribute SourceFile
  
  
  -keepattributes Signature
  
  -dontwarn okhttp3.**
  -keep class okhttp3.**{*;}
  -keep interface okhttp3.** { *; }
  
  #保留HomeFragment中所有变量的方法不被混淆
  -keep class com.example.pc.myapplication.HomeFragment{
   *;
  }
  
  #保留utils中未调用方法
  -keepclassmembers class com.example.pc.myapplication.utils.FileUtils {
  *;
  }
  
  #保留support包
  -keep class android.support.**{
  *;
  }
  </code></pre>
  
  <p>```</p>