Skip to content

Commit 0141b07

Browse files
committed
docs(README): add info
1 parent b00b806 commit 0141b07

File tree

2 files changed

+208
-2
lines changed

2 files changed

+208
-2
lines changed

JavaInfo

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,52 @@
11
#!/usr/bin/perl
22

3+
################################################################################
4+
# JavaInfo - Java Class File Version Analyzer
5+
#
6+
# This utility extracts Java version information from compiled class files by
7+
# reading their bytecode headers. It recursively processes files and directories
8+
# to identify Java class files and report their compilation version.
9+
#
10+
# The script reads the first 8 bytes of each file, checks for the Java class
11+
# file magic number (0xCAFEBABE), and extracts the major/minor version numbers
12+
# which indicate the Java version used to compile the class.
13+
#
14+
# Usage: JavaInfo <file or directory> [<file or directory> ...]
15+
#
16+
# Examples:
17+
# JavaInfo MyClass.class
18+
# JavaInfo /path/to/project/bin
19+
# JavaInfo target/classes lib/*.jar
20+
#
21+
# Author: Thomas
22+
# License: See LICENSE file
23+
################################################################################
24+
325
use strict;
426
use warnings;
527
use File::Spec::Functions;
628

29+
#
30+
# Main entry point - processes all command-line arguments
31+
#
32+
# Parameters:
33+
# @_ - List of file or directory paths to process
34+
#
735
sub main {
836
foreach my $node (@_) {
937
process_node($node);
1038
}
1139
}
1240

41+
#
42+
# Process a filesystem node (file or directory)
43+
#
44+
# Determines whether the given path is a file or directory and dispatches
45+
# to the appropriate handler function.
46+
#
47+
# Parameters:
48+
# $node - Path to the filesystem node to process
49+
#
1350
sub process_node {
1451
my $node = shift();
1552
if (-f $node) {
@@ -19,6 +56,19 @@ sub process_node {
1956
}
2057
}
2158

59+
#
60+
# Recursively process all files in a directory
61+
#
62+
# Reads all entries in the directory (excluding . and ..) and recursively
63+
# processes each one by calling process_node.
64+
#
65+
# Parameters:
66+
# $dir - Path to the directory to process
67+
#
68+
# Dies on error:
69+
# - If the directory cannot be opened
70+
# - If the directory contents cannot be read
71+
#
2272
sub process_dir {
2373
my $dir = shift();
2474
if (opendir(my $DIR, $dir)) {
@@ -35,17 +85,51 @@ sub process_dir {
3585
}
3686
}
3787

88+
#
89+
# Process a single file and extract Java version information
90+
#
91+
# Reads the first 8 bytes of a file to check if it's a valid Java class file
92+
# (identified by the magic number 0xCAFEBABE) and extracts version information
93+
# from the bytecode header.
94+
#
95+
# Java class file format (first 8 bytes):
96+
# Bytes 0-3: Magic number (0xCAFEBABE)
97+
# Bytes 4-5: Minor version
98+
# Bytes 6-7: Major version
99+
#
100+
# Version mapping:
101+
# Major 45 (minor <=3): Java 1.0.2
102+
# Major 45 (minor >3): Java 1.1.8
103+
# Major 46: Java 1.2.2
104+
# Major 47: Java 1.3.1
105+
# Major 48: Java 1.4.2
106+
# Major 49+: Java (major - 44) [e.g., 52 = Java 8, 61 = Java 17]
107+
#
108+
# Parameters:
109+
# $file - Path to the file to process
110+
#
111+
# Dies on error:
112+
# - If the file cannot be opened
113+
# - If the file cannot be read
114+
# - If the file is not a valid Java class file
115+
#
38116
sub process_file {
39117
my $file = shift();
40118
if (open(my $FILE, '<', $file)) {
41119
binmode($FILE);
42120
my $buffer;
43121
if (read(FILE, $buffer, 8)) {
122+
# Unpack the first 8 bytes as two 32-bit unsigned integers (big-endian)
44123
my @fields = unpack('NN', $buffer);
124+
125+
# Check for Java class file magic number (0xCAFEBABE)
45126
if ($fields[0] == 0xCAFEBABE) {
127+
# Extract minor and major version numbers from the second 32-bit value
46128
my $minor = ($fields[1] & 0xFF00) >> 16; ## no critic [Use of bitwise operator]: indeed
47129
my $major = $fields[1] & 0x00FF; ## no critic [Use of bitwise operator]: indeed
48130
my $version = '';
131+
132+
# Map major/minor version to Java release version
49133
if ($major == 45) {
50134
if ($minor <= 3) {
51135
$version = '1.0.2';
@@ -59,6 +143,7 @@ sub process_file {
59143
} elsif ($major == 48) {
60144
$version = '1.4.2';
61145
} elsif ($major >= 49) {
146+
# Java 5 and later: version = major - 44
62147
$version = ($major - 44);
63148
}
64149
print "$file: Java " . $version . " [" . $minor . "/" . $major . "]\n";

README.md

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,126 @@
11
# JavaInfo
22

3-
Perl utility to extract the Java version info from a class file's bytecode.
3+
A Perl utility to extract Java version information from compiled Java class files by analyzing their bytecode headers.
44

5-
[![PerlCritic](https://github.com/thomasleplus/JavaInfo/workflows/PerlCritic/badge.svg)](https://github.com/thomasleplus/JavaInfo/actions?query=workflow:"PerlCritic")
5+
## Description
6+
7+
JavaInfo reads Java `.class` files and identifies the Java version used to compile them. It works by examining the bytecode header of each class file, specifically the magic number (`0xCAFEBABE`) and the major/minor version numbers that indicate the Java compiler version.
8+
9+
The tool can process individual files or recursively scan entire directories, making it useful for:
10+
- Auditing Java dependencies and libraries
11+
- Verifying compilation targets in build artifacts
12+
- Identifying version mismatches in projects
13+
- Understanding compatibility requirements
14+
15+
## Requirements
16+
17+
- Perl 5.x or later
18+
- Standard Perl modules (included by default):
19+
- `File::Spec::Functions`
20+
21+
## Installation
22+
23+
1. Clone or download this repository
24+
2. Make the script executable:
25+
```bash
26+
chmod +x JavaInfo
27+
```
28+
3. Optionally, add it to your PATH:
29+
```bash
30+
sudo cp JavaInfo /usr/local/bin/
31+
```
32+
33+
## Usage
34+
35+
```bash
36+
./JavaInfo <file or directory> [<file or directory> ...]
37+
```
38+
39+
### Examples
40+
41+
**Analyze a single class file:**
42+
```bash
43+
./JavaInfo MyClass.class
44+
```
45+
46+
**Scan a directory recursively:**
47+
```bash
48+
./JavaInfo /path/to/project/target/classes
49+
```
50+
51+
**Process multiple paths:**
52+
```bash
53+
./JavaInfo src/main/java build/classes lib/*.jar
54+
```
55+
56+
### Example Output
57+
58+
```
59+
MyClass.class: Java 11 [0/55]
60+
Utils.class: Java 8 [0/52]
61+
LegacyCode.class: Java 1.4.2 [0/48]
62+
```
63+
64+
The output format is:
65+
```
66+
<filename>: Java <version> [<minor>/<major>]
67+
```
68+
69+
Where:
70+
- `<filename>` is the path to the class file
71+
- `<version>` is the Java version (e.g., 8, 11, 17, or 1.4.2 for older versions)
72+
- `<minor>/<major>` are the bytecode version numbers
73+
74+
## Java Version Mapping
75+
76+
The tool uses the following mapping between bytecode major versions and Java releases:
77+
78+
| Major Version | Minor Version | Java Version |
79+
|--------------|---------------|--------------|
80+
| 45 | 0-3 | 1.0.2 |
81+
| 45 | 4+ | 1.1.8 |
82+
| 46 | - | 1.2.2 |
83+
| 47 | - | 1.3.1 |
84+
| 48 | - | 1.4.2 |
85+
| 49 | - | 5 |
86+
| 50 | - | 6 |
87+
| 51 | - | 7 |
88+
| 52 | - | 8 |
89+
| 53 | - | 9 |
90+
| 54 | - | 10 |
91+
| 55 | - | 11 |
92+
| 56 | - | 12 |
93+
| 57 | - | 13 |
94+
| 58 | - | 14 |
95+
| 59 | - | 15 |
96+
| 60 | - | 16 |
97+
| 61 | - | 17 |
98+
| 62 | - | 18 |
99+
| 63 | - | 19 |
100+
| 64 | - | 20 |
101+
| 65 | - | 21 |
102+
103+
For Java 5 and later, the formula is: **Java Version = Major Version - 44**
104+
105+
## Error Handling
106+
107+
The script will display error messages and exit if:
108+
- A file cannot be opened or read
109+
- A directory cannot be accessed
110+
- A file is not a valid Java class file (missing the `0xCAFEBABE` magic number)
111+
112+
## Contributing
113+
114+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
115+
116+
## License
117+
118+
See [LICENSE](LICENSE) file for details.
119+
120+
## Security
121+
122+
For security concerns, please see [SECURITY.md](SECURITY.md).
123+
124+
## Code of Conduct
125+
126+
This project adheres to a code of conduct. See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for details.

0 commit comments

Comments
 (0)