@@ -89,7 +89,7 @@ static ClassDumper create(List<ClassPathEntry> entries) throws IOException {
8989 .collect (toImmutableList ());
9090 checkArgument (
9191 unreadableFiles .isEmpty (), "Some jar files are not readable: %s" , unreadableFiles );
92-
92+
9393 Map <String , ClassPathEntry > map = new HashMap <>();
9494 for (ClassPathEntry entry : entries ) {
9595 for (String className : entry .getFileNames ()) {
@@ -98,7 +98,7 @@ static ClassDumper create(List<ClassPathEntry> entries) throws IOException {
9898 }
9999 }
100100 }
101-
101+
102102 return new ClassDumper (entries , extensionClassLoader , map );
103103 }
104104
@@ -141,37 +141,54 @@ static boolean isArrayClass(String className) {
141141 return className .startsWith ("[" );
142142 }
143143
144- /**
145- * Returns a map from classes to the symbol references they contain.
146- */
144+ /** Returns a map from classes to the symbol references they contain. */
147145 SymbolReferences findSymbolReferences () throws IOException {
148146 SymbolReferences .Builder builder = new SymbolReferences .Builder ();
149147
150148 for (ClassPathEntry jar : inputClassPath ) {
149+ int totalClassFileCount = 0 ;
150+ int incompatibleClassFileCount = 0 ;
151151 for (JavaClass javaClass : listClasses (jar )) {
152+ totalClassFileCount ++;
152153 if (isCompatibleClassFileVersion (javaClass )) {
153154 String className = javaClass .getClassName ();
154155 // In listClasses(jar), ClassPathRepository creates JavaClass through the first JAR file
155156 // that contains the class. It may be different from "jar" for an overlapping class.
156157 ClassFile source = new ClassFile (findClassLocation (className ), className );
157158 builder .addAll (findSymbolReferences (source , javaClass ));
159+ } else {
160+ incompatibleClassFileCount ++;
158161 }
159162 }
163+ if (incompatibleClassFileCount > 0 ) {
164+ logger .warning (
165+ String .format (
166+ "%s has %d (out of %d) incompatible class files (class file major version is outside %d <= v <= %d)." ,
167+ jar ,
168+ incompatibleClassFileCount ,
169+ totalClassFileCount ,
170+ MINIMUM_CLASS_FILE_MAJOR_VERSION ,
171+ MAXIMUM_CLASS_FILE_MAJOR_VERSION ));
172+ }
160173 }
161174
162175 return builder .build ();
163176 }
164177
178+ private static final int MINIMUM_CLASS_FILE_MAJOR_VERSION = 45 ;
179+ private static final int MAXIMUM_CLASS_FILE_MAJOR_VERSION = 52 ;
180+
165181 /**
166- * Returns true if {@code javaClass} file format is compatible with this tool. Currently
167- * Java 8 and earlier are supported.
182+ * Returns true if {@code javaClass} file format is compatible with this tool. Currently Java 8
183+ * (class file major version 52) and earlier are supported.
168184 *
169185 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.1">Java
170186 * Virtual Machine Specification: The ClassFile Structure: minor_version, major_version</a>
171187 */
172188 private static boolean isCompatibleClassFileVersion (JavaClass javaClass ) {
173189 int classFileMajorVersion = javaClass .getMajor ();
174- return 45 <= classFileMajorVersion && classFileMajorVersion <= 52 ;
190+ return MINIMUM_CLASS_FILE_MAJOR_VERSION <= classFileMajorVersion
191+ && classFileMajorVersion <= MAXIMUM_CLASS_FILE_MAJOR_VERSION ;
175192 }
176193
177194 private static SymbolReferences .Builder findSymbolReferences (
@@ -182,7 +199,7 @@ private static SymbolReferences.Builder findSymbolReferences(
182199 Constant [] constants = constantPool .getConstantPool ();
183200 for (Constant constant : constants ) {
184201 if (constant == null ) {
185- continue ;
202+ continue ;
186203 }
187204
188205 byte constantTag = constant .getTag ();
@@ -262,8 +279,7 @@ private static ClassSymbol makeSymbol(
262279 return new ClassSymbol (targetClassName );
263280 }
264281
265- private static MethodSymbol makeSymbol (
266- ConstantCP constantMethodref , ConstantPool constantPool ) {
282+ private static MethodSymbol makeSymbol (ConstantCP constantMethodref , ConstantPool constantPool ) {
267283 String className = constantMethodref .getClass (constantPool );
268284 ConstantNameAndType constantNameAndType = constantNameAndType (constantMethodref , constantPool );
269285 String methodName = constantNameAndType .getName (constantPool );
@@ -303,7 +319,7 @@ static ImmutableSet<String> listInnerClassNames(JavaClass javaClass) {
303319 continue ;
304320 }
305321 }
306-
322+
307323 // Class names stored in constant pool have '/' as separator. We want '.' (as binary name)
308324 String normalInnerClassName = innerClassName .replace ('/' , '.' );
309325 innerClassNames .add (normalInnerClassName );
0 commit comments