blob: 06f2133c63652ef7aafe0fd0dec2379c11d452e5 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
package com.gemstone.gemfire.codeAnalysis.decode;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.Serializable;
import com.gemstone.gemfire.DataSerializable;
import com.gemstone.gemfire.LogWriter;
import com.gemstone.gemfire.codeAnalysis.decode.cp.Cp;
import com.gemstone.gemfire.codeAnalysis.decode.cp.CpClass;
import com.gemstone.gemfire.codeAnalysis.decode.cp.CpDouble;
import com.gemstone.gemfire.codeAnalysis.decode.cp.CpLong;
import com.gemstone.gemfire.internal.DataSerializableFixedID;
import com.gemstone.gemfire.internal.logging.PureLogWriter;
import com.gemstone.org.jgroups.util.StreamableFixedID;
/**
* Decoder represents a jdk ClassFile header
*/
public class CompiledClass implements Comparable {
public long magic;
public int minor_version;
public int major_version;
public int constant_pool_count;
public Cp constant_pool[];
public int access_flags;
public int this_class; // ptr into constant_pool
public int super_class; // ptr into constant_pool
public int interfaces_count;
public int interfaces[];
public int fields_count;
public CompiledField fields[];
public int methods_count;
public CompiledMethod methods[];
public int attributes_count;
public CompiledAttribute attributes[];
static LogWriter debugLog;
static PrintStream debugStream;
static {
try {
debugStream = new PrintStream("loadedClasses.log");
debugLog = new PureLogWriter(PureLogWriter.ALL_LEVEL, debugStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static CompiledClass getInstance( File classFile ) throws IOException {
FileInputStream fstream = new FileInputStream(classFile);
DataInputStream source = new DataInputStream(fstream);
CompiledClass instance = new CompiledClass(source);
fstream.close();
return instance;
}
public static CompiledClass getInstance( InputStream classStream ) throws IOException {
DataInputStream source = new DataInputStream(classStream);
CompiledClass instance = new CompiledClass(source);
classStream.close();
return instance;
}
/**
* read a ClassFile structure from the given input source (usually a file)
*/
public CompiledClass( DataInputStream source ) throws IOException {
int idx;
magic = (long)source.readInt();
minor_version = source.readUnsignedShort();
major_version = source.readUnsignedShort();
// the first constant-pool slot is reserved by Java and is not in the classes file
constant_pool_count = source.readUnsignedShort();
// read the constant pool list
constant_pool = new Cp[constant_pool_count];
constant_pool[0] = null;
for (idx=1; idx<constant_pool_count; idx++) {
constant_pool[idx] = Cp.readCp(source);
// from Venkatesh: workaround for Javasoft hack
// From the Java Virtual Machine Specification,
// all eight-byte constants take up two spots in the constant pool.
// If this is the nth item in the constant pool, then the next
// item will be numbered n+2.
if ((constant_pool[idx] instanceof CpLong) ||
(constant_pool[idx] instanceof CpDouble)) idx++;
}
access_flags = source.readUnsignedShort();
this_class = source.readUnsignedShort();
super_class = source.readUnsignedShort();
interfaces_count = source.readUnsignedShort();
// read the interfaces list (ptrs into constant_pool)
interfaces = new int[interfaces_count];
for (idx=0; idx<interfaces_count; idx++) {
interfaces[idx] = source.readUnsignedShort();
}
fields_count = source.readUnsignedShort();
// read the fields list (only includes this class, not inherited variables)
fields = new CompiledField[fields_count];
for (idx=0; idx<fields_count; idx++) {
fields[idx] = new CompiledField(source, this);
}
methods_count = source.readUnsignedShort();
// read the methods list
methods = new CompiledMethod[methods_count];
for (idx=0; idx<methods_count; idx++) {
methods[idx] = new CompiledMethod(source, this);
}
attributes_count = source.readUnsignedShort();
// read the attributes
attributes = new CompiledAttribute[attributes_count];
for (idx=0; idx<attributes_count; idx++) {
attributes[idx] = new CompiledAttribute(source);
}
}
String accessString() {
StringBuffer result;
result = new StringBuffer();
if ((access_flags & 0x0001) != 0)
result.append("public ");
if ((access_flags & 0x0002) != 0)
result.append("(private?) ");
if ((access_flags & 0x0004) != 0)
result.append("(protected?) ");
if ((access_flags & 0x0008) != 0)
result.append("(static?) ");
if ((access_flags & 0x0010) != 0)
result.append("final ");
if ((access_flags & 0x0020) != 0)
result.append("(??0x20??) ");
if ((access_flags & 0x0040) != 0)
result.append("(volatile?) ");
if ((access_flags & 0x0080) != 0)
result.append("(transient?) ");
if ((access_flags & 0x0100) != 0)
result = result.append("(??0x100??) ");
if ((access_flags & 0x0200) != 0)
result = result.append("interface ");
if ((access_flags & 0x0400) != 0)
result = result.append("abstract ");
if ((access_flags & 0x0800) != 0)
result = result.append("(??0x800??) ");
return result.toString();
}
public boolean isInterface() {
return (access_flags & 0x0200) != 0;
}
public boolean isSerializableAndNotDataSerializable() {
// these classes throw exceptions or log ugly messages when you try to load them
// in junit
String name = fullyQualifiedName().replace('/', '.');
if (name.startsWith("com.gemstone.gemfire.internal.shared.NativeCallsJNAImpl")
|| name.startsWith("com.gemstone.gemfire.internal.HostStatHelper")) {
return false;
}
try {
debugLog.info("isSerializableAndNotDataSerializable loading class " + name);
debugStream.flush();
Class realClass = Class.forName(name);
return Serializable.class.isAssignableFrom(realClass)
&& !DataSerializable.class.isAssignableFrom(realClass)
&& !DataSerializableFixedID.class.isAssignableFrom(realClass)
&& !StreamableFixedID.class.isAssignableFrom(realClass);
} catch (UnsatisfiedLinkError e) {
System.out.println("Unable to load actual class " + name + " external JNI dependencies");
} catch (NoClassDefFoundError e) {
System.out.println("Unable to load actual class " + name + " not in JUnit classpath");
} catch (Throwable e) {
System.out.println("Unable to load actual class " + name + ": " + e);
}
return false;
}
public String fullyQualifiedName() {
return ((CpClass)constant_pool[this_class]).className(this);
}
public String superClassName() {
return ((CpClass)constant_pool[super_class]).className(this);
}
public int compareTo(Object other) {
if ( ! (other instanceof CompiledClass) ) {
return -1;
}
String otherName = ((CompiledClass)other).fullyQualifiedName();
return this.fullyQualifiedName().compareTo(otherName);
}
public static void main(String argv[]) {
File classFile;
CompiledClass instance;
int idx;
classFile = null;
try {
classFile = new File(argv[0]); }
catch (NullPointerException e) {
System.err.println("You must give the name of a class file on the command line");
exit(3);
}
if (classFile == null) {
System.err.println("Unable to access " + argv[0]);
exit(3);
}
if (!classFile.canRead()) {
System.err.println("Unable to read " + argv[0]);
exit(3);
}
try {
instance = getInstance(classFile);
System.out.println("Class name is " + instance.fullyQualifiedName());
System.out.println("Class access is " + instance.accessString());
System.out.println("Superclass name is " + instance.superClassName());
System.out.println("Fields:");
for (idx=0; idx<instance.fields_count; idx++) {
System.out.println(" " + instance.fields[idx].signature());
}
System.out.println("Methods:");
for (idx=0; idx<instance.methods_count; idx++) {
System.out.println(" " + instance.methods[idx].signature());
// if (idx == 0) {
System.out.println("..method attributes");
for (int i=0; i<instance.methods[idx].attributes_count; i++) {
System.out.println(".."+instance.methods[idx].attributes[i].name(instance));
}
// }
}
} catch (Throwable e) {
System.err.println("Error reading file: " + e.getMessage());
exit(3);
}
exit(0);
}
private static void exit(int exitCode) {
int b;
// if (false) {
// if (exitCode == 0)
// System.out.println("Done - press Enter to exit: ");
// else
// System.out.println("Press Enter to exit:");
// try {
// b = System.in.read();
// } catch (java.io.IOException e) {};
// }
System.exit(exitCode);
}
}