Several GlassFish bugs have been discovered when running with Java SE 7 due to a change in the return value of the Class.getMethods and Class.getDeclaredMethods calls. This page discusses the change in the Java SE implementation, examples of GlassFish bugs that have already been found and why the bugs only showed up with Java SE 7, and examples of how to fix this issue.
The Class.getMethods javadoc (and Class.getDeclaredMethods) from Java SE 6 says:
The elements in the array returned are not sorted and are not in any particular order.
Despite this statement, up through Java SE 6 and up until build 128 of Java SE 7, the methods were returned in a consistent order from run to run of the JVM and within a single run. However, starting with build 129 of Java SE 7, according to bug 7023180, there was a change in the implementation of the JVM that causes the order of the methods in the return value to vary, both from run to run and within a single run of the JVM. So for example, given the following class:
One call to A.class.getMethods() might return [ getX, getY ] while another call might return [ getY, getX ]. The actual order depends on class loading, the JVM symbol table, and various other factors within the JVM.
Several JIRA bugs (18133, 18184, 18368) have been filed against GlassFish where the root cause is due to this change. In each of these cases, there is a loop over the return value of Class.getMethods, and the logic within the loop is looking for a method with particular characteristics. However, the logic was not precise enough about the method being sought, and with earlier JVM releases, the code happened to find the method it was looking for first. With newer Java SE 7 releases, a different (wrong) method is found. For example, consider bug 18133. Here, the loop looks like this:
.The class referenced by parentType has the following two methods:
The string methodName in this case is "getNode". Depending on the order of the array returned by getMethods, this loop may find either of the methods. Later in the method, targetMethod.invoke is called, expecting to pass in no arguments. If the second method is found by the loop, the invoke call throws an exception.
The fix for the bug depends on the what the loop is actually searching for. In this case, the method not only has to have the given name, but it must also be annotated with an annotation that extends the InhabitantAnnotation. So to correct this code, the if statement in the loop has to be changed to check not only for the name of the method, but for the desired annotation.
With the other bugs, the check that is made on the method is more complex, and in each case, the fix was to add a more specific check on the method, either looking for the number of parameters that the method accepts or the methods return type.
Using Netbeans we've attempted to search the GlassFish trunk for all uses of Class.getMethods(), Class.getDeclaredMethods(). Those results are summarized on the following wiki page:
Tasks have been created to track code inspection of the files in the above list. You can see those tasks here: