Friday Stats: classfile versioning tool
Stuart Marks
stuart.marks at oracle.com
Fri Jun 21 18:44:11 PDT 2013
Hi all, nice project ya got here!
Here's a script and some Friday stats for you. I've written a script that
prints out the class file versions of class files and classes found within jar
files. The script is calls "classvers" and I've attached a patch to add it to
the repo.
Basically when run it and it will take a list of jars or classes. For each
class, it lists the class file version number and the class file name. For each
jar file, it unpacks the jar into a temp area and lists the classes and
versions of classfiles within that jar. If given no arguments, it searches the
hierarchy beneath the current working directory and prints out class file
versions for all class and jar files found.
(Oh, I guess I should have added that as help text to the script.)
I ran it over JDK 7 Update 25, and the output is like the following:
---------
48 db/lib/derby.jar!/org/apache/derby/authentication/SystemPrincipal.class
48 db/lib/derby.jar!/org/apache/derby/authentication/UserAuthenticator.class
48 db/lib/derby.jar!/org/apache/derby/catalog/AliasInfo.class
48 db/lib/derby.jar!/org/apache/derby/catalog/DefaultInfo.class
48 db/lib/derby.jar!/org/apache/derby/catalog/Dependable.class
... 47,025 lines omitted ...
---------
Who cares about class file versions? Well, given the entire output in
classes.list, one can generate a few summary statistics, like so:
awk '{print $1}' classes.list | sort -k 1n | uniq -c
18 45
1315 47
2672 48
2631 49
14850 50
25544 51
Looking at Joe Darcy's class file version decoder ring [1], one can see that
the latest JDK 7 update release contains mostly JDK 7 classes, lots of JDK 6
classes, a fair number of classes from JDK 5, JDK 1.4, and JDK 1.3, and even a
handful of files in the JDK 1.1 format!
(I'll leave it as an exercise to the reader to find out which classes are the
JDK 1.1 versions.)
Enjoy,
s'marks
[1] https://blogs.oracle.com/darcy/entry/source_target_class_file_version
-------------- next part --------------
# HG changeset patch
# User smarks
# Date 1371864704 25200
# Node ID 8a9e02901ded7df14ec55568313ce08cb2f6109a
# Parent 49376e5d18f1c0a7fbac8dad5b21fddff45d0134
Add class file versioning script.
diff -r 49376e5d18f1 -r 8a9e02901ded scripts/classvers
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/classvers Fri Jun 21 18:31:44 2013 -0700
@@ -0,0 +1,74 @@
+#!/bin/bash
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+TMPDIR=/tmp/classvers$$
+trap 'rm -rf $TMPDIR; exit 0' 0 1 2 3 15
+
+# oneclass classfile prefix
+# extracts class version byte in hex
+# od output is like:
+# 0000007 34
+function oneclass {
+ vers=$(od -t u1 -j 7 -N 1 "$1" | awk '$1 == 0000007 { print $2 }')
+ echo $vers $2$1
+}
+
+# findclasses [prefix]
+function findclasses {
+ find . -name '*.class' -print |
+ while read clname ; do
+ clname=${clname#./}
+ oneclass "$clname" "$1"
+ done
+}
+
+# onejar jarfile
+function onejar {
+ mkdir $TMPDIR
+ ( cd $TMPDIR
+ jar -x
+ findclasses "${1}!/"
+ ) < $1
+ rm -rf $TMPDIR
+}
+
+function classorjar {
+ case "$1" in
+ *.class)
+ oneclass "$1"
+ ;;
+ *.jar)
+ onejar "$1"
+ ;;
+ esac
+}
+
+if [ $# -eq 0 ]; then
+ find . \( -name '*.class' -o -name '*.jar' \) -print |
+ while read f ; do
+ classorjar "${f#./}"
+ done
+else
+ for arg in "$@" ; do
+ classorjar "$arg"
+ done
+fi
More information about the friday-stats-dev
mailing list