Skip to content

Instantly share code, notes, and snippets.

@soren
Created March 17, 2012 11:19
Show Gist options
  • Save soren/2057725 to your computer and use it in GitHub Desktop.
Save soren/2057725 to your computer and use it in GitHub Desktop.
Perl script that can determine the version of a java class file
#!/usr/bin/env perl
use warnings;
use strict;
use Pod::Usage;
=head1 NAME
java_class_version.pl - determines the version of a java class file
=head1 USAGE
java_class_version.pl [class file ...]
Example:
$ java_class_version.pl *.class
AbstractFacesServlet.class 6 (1.6) (50.0)
AbstractFacesServlet$InnerFacesContext.class 6 (1.6) (50.0)
DocumentServlet.class 6 (1.6) (50.0)
=head1 OPTIONS
No options. But if you call the script without any class file names it
will display its manual page.
=head1 DESCRIPTION
This script can tell you the version of a java class file. This can
come in handy if you want to deploy some third party jar on an older
platform. You don't need to do a try-and-error, but can determine
compability upfront.
The class file format is descibed in [ClassFile.doc]. The important
parts are the first eight bytes, that contain a magic number, the
minor and the major version of the file. It looks like this for a java
5 class file:
+----+----+----+----+----+----+----+----+
| ca | fe | ba | be | 00 | 00 | 00 | 31 |
+----+----+----+----+----+----+----+----+
| magcic number | minor | major |
+-------------------+---------+---------+
The integers are always stored in big-endian order, also know as
network order.
What java platform supports which class file version is a little fuzzy
for the first 1.0 and 1.1 releases. But
[source_target_class_file_version] has a nice summary, that at least
is simple for all later releases.
=for text
=encoding utf-8
=end
=head1 AUTHOR
Søren Lund, C<< <soren at lund.org> >>
=head1 SEE ALSO
=over
=item [ClassFile.doc]
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html
=item [source_target_class_file_version]
http://blogs.sun.com/darcy/entry/source_target_class_file_version
=back
=head1 COPYRIGHT
Copyright (C) 2012 Søren Lund
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991 or at your option
any later version.
This program 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 for more details.
A copy of the GNU General Public License is available in the source tree;
if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
=cut
my %java_platforms = (
"45.3" => "1.1",
"46.0" => "1.2",
"47.0" => "1.3",
"48.0" => "1.4",
"49.0" => "5 (1.5)",
"50.0" => "6 (1.6)",
"51.0" => "7 (1.7)"
);
pod2usage(-verbose => 2) if $#ARGV < 0;
foreach my $arg (@ARGV) {
open my $file, '<', $arg or die $!;
my $magic = read_int($file, 4);
if ($magic != 0xcafebabe) {
printf STDERR "%s is not a valid Java class.\n", $arg;
} else {
my $minor = read_int($file, 2);
my $major = read_int($file, 2);
my $version = sprintf("%d.%d", $major, $minor);
printf "%s %s (%s)\n", $arg, $java_platforms{$version}, $version;
}
close $file;
}
sub read_int {
my ($file, $size) = (@_);
my $data;
read $file, $data, $size;
return unpack($size==2?'n':'N',$data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment