71 Enumeration<JarEntry> e = jarFile.entries(); |
71 Enumeration<JarEntry> e = jarFile.entries(); |
72 int unsupportedClasses = 0; |
72 int unsupportedClasses = 0; |
73 System.out.print(jarFilePath); |
73 System.out.print(jarFilePath); |
74 while (e.hasMoreElements()) { |
74 while (e.hasMoreElements()) { |
75 JarEntry je = e.nextElement(); |
75 JarEntry je = e.nextElement(); |
76 if (je.isDirectory() || !je.getName().endsWith(".class")) { |
76 if (je.isDirectory() || !je.getName().endsWith(".class") || je.getName().equals("module-info.class")) { |
77 continue; |
77 continue; |
78 } |
78 } |
79 Set<String> methodAnnotationTypes = new HashSet<>(); |
79 Set<String> methodAnnotationTypes = new HashSet<>(); |
80 DataInputStream stream = new DataInputStream(new BufferedInputStream(jarFile.getInputStream(je), (int) je.getSize())); |
80 DataInputStream stream = new DataInputStream(new BufferedInputStream(jarFile.getInputStream(je), (int) je.getSize())); |
81 boolean isSupported = true; |
81 boolean isSupported = true; |
82 try { |
82 try { |
83 readClassfile(stream, methodAnnotationTypes); |
83 readClassfile(stream, methodAnnotationTypes); |
84 } catch (UnsupportedClassVersionError ucve) { |
84 } catch (UnsupportedClassVersionError ucve) { |
85 isSupported = false; |
85 isSupported = false; |
86 unsupportedClasses++; |
86 unsupportedClasses++; |
|
87 } catch (Throwable t) { |
|
88 throw new InternalError("Error while parsing class from " + je + " in " + jarFilePath, t); |
87 } |
89 } |
88 String className = je.getName().substring(0, je.getName().length() - ".class".length()).replaceAll("/", "."); |
90 String className = je.getName().substring(0, je.getName().length() - ".class".length()).replaceAll("/", "."); |
89 if (!isSupported) { |
91 if (!isSupported) { |
90 System.out.print(" !" + className); |
92 System.out.print(" !" + className); |
91 } |
93 } |
127 } |
129 } |
128 |
130 |
129 /* |
131 /* |
130 * Small bytecode parser that extract annotations. |
132 * Small bytecode parser that extract annotations. |
131 */ |
133 */ |
132 private static final int MAJOR_VERSION_JAVA7 = 51; |
134 private static final int MAJOR_VERSION_JAVA6 = 50; |
133 private static final int MAJOR_VERSION_OFFSET = 44; |
135 private static final int MAJOR_VERSION_OFFSET = 44; |
134 private static final byte CONSTANT_Utf8 = 1; |
136 private static final byte CONSTANT_Utf8 = 1; |
135 private static final byte CONSTANT_Integer = 3; |
137 private static final byte CONSTANT_Integer = 3; |
136 private static final byte CONSTANT_Float = 4; |
138 private static final byte CONSTANT_Float = 4; |
137 private static final byte CONSTANT_Long = 5; |
139 private static final byte CONSTANT_Long = 5; |
144 private static final byte CONSTANT_NameAndType = 12; |
146 private static final byte CONSTANT_NameAndType = 12; |
145 private static final byte CONSTANT_MethodHandle = 15; |
147 private static final byte CONSTANT_MethodHandle = 15; |
146 private static final byte CONSTANT_MethodType = 16; |
148 private static final byte CONSTANT_MethodType = 16; |
147 private static final byte CONSTANT_Dynamic = 17; |
149 private static final byte CONSTANT_Dynamic = 17; |
148 private static final byte CONSTANT_InvokeDynamic = 18; |
150 private static final byte CONSTANT_InvokeDynamic = 18; |
|
151 private static final byte CONSTANT_Module = 19; |
|
152 private static final byte CONSTANT_Package = 20; |
149 |
153 |
150 private static void readClassfile(DataInputStream stream, Collection<String> methodAnnotationTypes) throws IOException { |
154 private static void readClassfile(DataInputStream stream, Collection<String> methodAnnotationTypes) throws IOException { |
151 // magic |
155 // magic |
152 int magic = stream.readInt(); |
156 int magic = stream.readInt(); |
153 assert magic == 0xCAFEBABE; |
157 assert magic == 0xCAFEBABE; |
154 |
158 |
155 int minor = stream.readUnsignedShort(); |
159 int minor = stream.readUnsignedShort(); |
156 int major = stream.readUnsignedShort(); |
160 int major = stream.readUnsignedShort(); |
157 if (major < MAJOR_VERSION_JAVA7) { |
161 if (major < MAJOR_VERSION_JAVA6) { |
158 throw new UnsupportedClassVersionError("Unsupported class file version: " + major + "." + minor); |
162 throw new UnsupportedClassVersionError("Unsupported class file version: " + major + "." + minor); |
159 } |
163 } |
160 // Starting with JDK8, ignore a classfile that has a newer format than the current JDK. |
164 // Starting with JDK8, ignore a classfile that has a newer format than the current JDK. |
161 String javaVersion = System.getProperties().get("java.specification.version").toString(); |
165 String javaVersion = System.getProperties().get("java.specification.version").toString(); |
162 int majorJavaVersion; |
166 int majorJavaVersion; |
208 while (i < count) { |
212 while (i < count) { |
209 byte tag = stream.readByte(); |
213 byte tag = stream.readByte(); |
210 switch (tag) { |
214 switch (tag) { |
211 case CONSTANT_Class: |
215 case CONSTANT_Class: |
212 case CONSTANT_String: |
216 case CONSTANT_String: |
213 case CONSTANT_MethodType: { |
217 case CONSTANT_MethodType: |
|
218 case CONSTANT_Module: |
|
219 case CONSTANT_Package: { |
214 skipFully(stream, 2); |
220 skipFully(stream, 2); |
215 break; |
221 break; |
216 } |
222 } |
217 case CONSTANT_InterfaceMethodref: |
223 case CONSTANT_InterfaceMethodref: |
218 case CONSTANT_Methodref: |
224 case CONSTANT_Methodref: |