Java/Reflection/Class — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
|
(нет различий)
|
Текущая версия на 06:01, 1 июня 2010
Содержание
- 1 Access the enclosing class from an inner class
- 2 Class file reader for obtaining the parameter names for declared methods in a class
- 3 Class reflection
- 4 Class Reflection: class modifier
- 5 Class Reflection: class name
- 6 Class Reflection: name for super class
- 7 Convert a given String into the appropriate Class.
- 8 CrossRef prints a cross-reference about all classes named in argv
- 9 Demonstrate classFor to create an instance of an object
- 10 Demonstration of speed of reflexive versus programmatic invocation
- 11 Dump a class using Reflection
- 12 Encapsulates a class serialVersionUID and codebase.
- 13 Get the class By way of a string
- 14 Get the class By way of .class
- 15 JavaP prints structural information about classes
- 16 Load the class source location from Class.getResource()
- 17 Make up a compilable version of a given Sun or other API
- 18 Manipulate Java classes
- 19 Manipulate Java class files in strange and mysterious ways
- 20 Object Reflection: create new instance
- 21 Provides a set of static methods that extend the Java metaobject
- 22 Reflect1 shows the information about the class named in argv
- 23 Return a String representation of an object"s overall identity
- 24 Show a couple of things you can do with a Class object
- 25 Show that you can, in fact, take the class of a primitive
- 26 Show the class keyword and getClass() method in action
- 27 Simple Demonstration of a ClassLoader WILL NOT COMPILE OUT OF THE BOX
- 28 This class shows using Reflection to get a field from another class
- 29 Use reflection to dynamically discover the capabilities of a class.
- 30 Use reflection to get console char set
Access the enclosing class from an inner class
public class Main {
public static void main(String a[]){
new TestIt().doit();
}
public void doit() {
new InnerClass().sayHello();
}
public void enclosingClassMethod(){
System.out.println("Hello world!");
}
class InnerClass {
public void sayHello() {
TestIt.this.enclosingClassMethod();
}
}
}
Class file reader for obtaining the parameter names for declared methods in a class
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* This is the class file reader for obtaining the parameter names for declared
* methods in a class. The class must have debugging attributes for us to obtain
* this information.
* <p>
* This does not work for inherited methods. To obtain parameter names for
* inherited methods, you must use a paramReader for the class that originally
* declared the method.
* <p>
* don"t get tricky, it"s the bare minimum. Instances of this class are not
* threadsafe -- don"t share them.
* <p>
*
* @author Edwin Smith, Macromedia
*/
public class ClassReader extends ByteArrayInputStream {
// constants values that appear in java class files,
// from jvm spec 2nd ed, section 4.4, pp 103
private static final int CONSTANT_CLASS = 7;
private static final int CONSTANT_FIELDREF = 9;
private static final int CONSTANT_METHODREF = 10;
private static final int CONSTANT_INTERFACE_METHOD_REF = 11;
private static final int CONSTANT_STRING = 8;
private static final int CONSTANT_INTEGER = 3;
private static final int CONSTANT_FLOAT = 4;
private static final int CONSTANT_LONG = 5;
private static final int CONSTANT_DOUBLE = 6;
private static final int CONSTANT_NAME_AND_TYPE = 12;
private static final int CONSTANT_UTF_8 = 1;
/**
* the constant pool. constant pool indices in the class file directly index
* into this array. The value stored in this array is the position in the
* class file where that constant begins.
*/
private int[] cpoolIndex;
private Object[] cpool;
private Map<String, Method> attrMethods;
protected ClassReader(byte buf[], Map<String, Method> attrMethods) {
super(buf);
this.attrMethods = attrMethods;
}
/**
* load the bytecode for a given class, by using the class"s defining
* classloader and assuming that for a class named P.C, the bytecodes are in
* a resource named /P/C.class.
*
* @param c the class of interest
* @return a byte array containing the bytecode
* @throws IOException
*/
protected static byte[] getBytes(Class c) throws IOException {
InputStream fin = c.getResourceAsStream("/" + c.getName().replace(".", "/") + ".class");
if (fin == null) {
throw new IOException();
}
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int actual;
do {
actual = fin.read(buf);
if (actual > 0) {
out.write(buf, 0, actual);
}
} while (actual > 0);
return out.toByteArray();
} finally {
fin.close();
}
}
static String classDescriptorToName(String desc) {
return desc.replace("/", ".");
}
protected static Map<String, Method> findAttributeReaders(Class c) {
Map<String, Method> map = new HashMap<String, Method>();
Method[] methods = c.getMethods();
for (int i = 0; i < methods.length; i++) {
String name = methods[i].getName();
if (name.startsWith("read") && methods[i].getReturnType() == void.class) {
map.put(name.substring(4), methods[i]);
}
}
return map;
}
protected static String getSignature(Member method, Class[] paramTypes) {
// compute the method descriptor
StringBuffer b = new StringBuffer((method instanceof Method) ? method.getName() : "<init>");
b.append("(");
for (int i = 0; i < paramTypes.length; i++) {
addDescriptor(b, paramTypes[i]);
}
b.append(")");
if (method instanceof Method) {
addDescriptor(b, ((Method)method).getReturnType());
} else if (method instanceof Constructor) {
addDescriptor(b, void.class);
}
return b.toString();
}
private static void addDescriptor(StringBuffer b, Class c) {
if (c.isPrimitive()) {
if (c == void.class) {
b.append("V");
} else if (c == int.class) {
b.append("I");
} else if (c == boolean.class) {
b.append("Z");
} else if (c == byte.class) {
b.append("B");
} else if (c == short.class) {
b.append("S");
} else if (c == long.class) {
b.append("J");
} else if (c == char.class) {
b.append("C");
} else if (c == float.class) {
b.append("F");
} else if (c == double.class) {
b.append("D");
}
} else if (c.isArray()) {
b.append("[");
addDescriptor(b, c.getComponentType());
} else {
b.append("L").append(c.getName().replace(".", "/")).append(";");
}
}
/**
* @return the next unsigned 16 bit value
*/
protected final int readShort() {
return (read() << 8) | read();
}
/**
* @return the next signed 32 bit value
*/
protected final int readInt() {
return (read() << 24) | (read() << 16) | (read() << 8) | read();
}
/**
* skip n bytes in the input stream.
*/
protected void skipFully(int n) throws IOException {
while (n > 0) {
int c = (int)skip(n);
if (c <= 0) {
throw new EOFException();
}
n -= c;
}
}
protected final Member resolveMethod(int index) throws IOException, ClassNotFoundException,
NoSuchMethodException {
int oldPos = pos;
try {
Member m = (Member)cpool[index];
if (m == null) {
pos = cpoolIndex[index];
Class owner = resolveClass(readShort());
NameAndType nt = resolveNameAndType(readShort());
String signature = nt.name + nt.type;
if ("<init>".equals(nt.name)) {
Constructor[] ctors = owner.getConstructors();
for (int i = 0; i < ctors.length; i++) {
String sig = getSignature(ctors[i], ctors[i].getParameterTypes());
if (sig.equals(signature)) {
cpool[index] = ctors[i];
m = ctors[i];
return m;
}
}
} else {
Method[] methods = owner.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
String sig = getSignature(methods[i], methods[i].getParameterTypes());
if (sig.equals(signature)) {
cpool[index] = methods[i];
m = methods[i];
return m;
}
}
}
throw new NoSuchMethodException(signature);
}
return m;
} finally {
pos = oldPos;
}
}
protected final Field resolveField(int i) throws IOException, ClassNotFoundException,
NoSuchFieldException {
int oldPos = pos;
try {
Field f = (Field)cpool[i];
if (f == null) {
pos = cpoolIndex[i];
Class owner = resolveClass(readShort());
NameAndType nt = resolveNameAndType(readShort());
cpool[i] = owner.getDeclaredField(nt.name);
f = owner.getDeclaredField(nt.name);
}
return f;
} finally {
pos = oldPos;
}
}
protected final NameAndType resolveNameAndType(int i) throws IOException {
int oldPos = pos;
try {
NameAndType nt = (NameAndType)cpool[i];
if (nt == null) {
pos = cpoolIndex[i];
String name = resolveUtf8(readShort());
String type = resolveUtf8(readShort());
cpool[i] = new NameAndType(name, type);
nt = new NameAndType(name, type);
}
return nt;
} finally {
pos = oldPos;
}
}
protected final Class resolveClass(int i) throws IOException, ClassNotFoundException {
int oldPos = pos;
try {
Class c = (Class)cpool[i];
if (c == null) {
pos = cpoolIndex[i];
String name = resolveUtf8(readShort());
cpool[i] = Class.forName(classDescriptorToName(name));
c = Class.forName(classDescriptorToName(name));
}
return c;
} finally {
pos = oldPos;
}
}
protected final String resolveUtf8(int i) throws IOException {
int oldPos = pos;
try {
String s = (String)cpool[i];
if (s == null) {
pos = cpoolIndex[i];
int len = readShort();
skipFully(len);
cpool[i] = new String(buf, pos - len, len, "utf-8");
s = new String(buf, pos - len, len, "utf-8");
}
return s;
} finally {
pos = oldPos;
}
}
@SuppressWarnings("fallthrough")
protected final void readCpool() throws IOException {
int count = readShort(); // cpool count
cpoolIndex = new int[count];
cpool = new Object[count];
for (int i = 1; i < count; i++) {
int c = read();
cpoolIndex[i] = super.pos;
// constant pool tag
switch (c) {
case CONSTANT_FIELDREF:
case CONSTANT_METHODREF:
case CONSTANT_INTERFACE_METHOD_REF:
case CONSTANT_NAME_AND_TYPE:
readShort(); // class index or (12) name index
// fall through
case CONSTANT_CLASS:
case CONSTANT_STRING:
readShort(); // string index or class index
break;
case CONSTANT_LONG:
case CONSTANT_DOUBLE:
readInt(); // hi-value
// see jvm spec section 4.4.5 - double and long cpool
// entries occupy two "slots" in the cpool table.
i++;
// fall through
case CONSTANT_INTEGER:
case CONSTANT_FLOAT:
readInt(); // value
break;
case CONSTANT_UTF_8:
int len = readShort();
skipFully(len);
break;
default:
// corrupt class file
throw new IllegalStateException();
}
}
}
protected final void skipAttributes() throws IOException {
int count = readShort();
for (int i = 0; i < count; i++) {
readShort(); // name index
skipFully(readInt());
}
}
/**
* read an attributes array. the elements of a class file that can contain
* attributes are: fields, methods, the class itself, and some other types
* of attributes.
*/
protected final void readAttributes() throws IOException {
int count = readShort();
for (int i = 0; i < count; i++) {
int nameIndex = readShort(); // name index
int attrLen = readInt();
int curPos = pos;
String attrName = resolveUtf8(nameIndex);
Method m = attrMethods.get(attrName);
if (m != null) {
try {
m.invoke(this, new Object[] {});
} catch (IllegalAccessException e) {
pos = curPos;
skipFully(attrLen);
} catch (InvocationTargetException e) {
try {
throw e.getTargetException();
} catch (Error ex) {
throw ex;
} catch (RuntimeException ex) {
throw ex;
} catch (IOException ex) {
throw ex;
} catch (Throwable ex) {
pos = curPos;
skipFully(attrLen);
}
}
} else {
// don"t care what attribute this is
skipFully(attrLen);
}
}
}
/**
* read a code attribute
*
* @throws IOException
*/
public void readCode() throws IOException {
readShort(); // max stack
readShort(); // max locals
skipFully(readInt()); // code
skipFully(8 * readShort()); // exception table
// read the code attributes (recursive). This is where
// we will find the LocalVariableTable attribute.
readAttributes();
}
private static class NameAndType {
String name;
String type;
public NameAndType(String name, String type) {
this.name = name;
this.type = type;
}
}
}
Class reflection
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ShowClass {
public static void main(String[] args) throws ClassNotFoundException {
Class aClass = Class.forName("javax.swing.JComponent");
if (aClass.isInterface()) {
System.out.print(Modifier.toString(aClass.getModifiers()) + " "
+ typeName(aClass));
} else if (aClass.getSuperclass() != null) {
System.out.print(Modifier.toString(aClass.getModifiers()) + " class "
+ typeName(aClass) + " extends " + typeName(aClass.getSuperclass()));
} else {
System.out.print(Modifier.toString(aClass.getModifiers()) + " class "
+ typeName(aClass));
}
Class[] interfaces = aClass.getInterfaces();
if ((interfaces != null) && (interfaces.length > 0)) {
if (aClass.isInterface())
System.out.print(" extends ");
else
System.out.print(" implements ");
for (int i = 0; i < interfaces.length; i++) {
if (i > 0)
System.out.print(", ");
System.out.print(typeName(interfaces[i]));
}
}
System.out.println(" {");
Constructor[] constructors = aClass.getDeclaredConstructors();
for (int i = 0; i < constructors.length; i++)
printMethodOrConstructor(constructors[i]);
Field[] fields = aClass.getDeclaredFields();
for (int i = 0; i < fields.length; i++)
printField(fields[i]);
Method[] methods = aClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++)
printMethodOrConstructor(methods[i]);
System.out.println("}");
}
public static String typeName(Class t) {
String brackets = "";
while (t.isArray()) {
brackets += "[]";
t = t.getComponentType();
}
String name = t.getName();
int pos = name.lastIndexOf(".");
if (pos != -1)
name = name.substring(pos + 1);
return name + brackets;
}
public static String modifiers(int m) {
if (m == 0)
return "";
else
return Modifier.toString(m) + " ";
}
public static void printField(Field f) {
System.out.println(" " + modifiers(f.getModifiers())
+ typeName(f.getType()) + " " + f.getName() + ";");
}
public static void printMethodOrConstructor(Member member) {
Class returntype = null, parameters[], exceptions[];
if (member instanceof Method) {
Method m = (Method) member;
returntype = m.getReturnType();
parameters = m.getParameterTypes();
exceptions = m.getExceptionTypes();
System.out.print(" " + modifiers(member.getModifiers())
+ typeName(returntype) + " " + member.getName() + "(");
} else {
Constructor c = (Constructor) member;
parameters = c.getParameterTypes();
exceptions = c.getExceptionTypes();
System.out.print(" " + modifiers(member.getModifiers())
+ typeName(c.getDeclaringClass()) + "(");
}
for (int i = 0; i < parameters.length; i++) {
if (i > 0)
System.out.print(", ");
System.out.print(typeName(parameters[i]));
}
System.out.print(")");
if (exceptions.length > 0)
System.out.print(" throws ");
for (int i = 0; i < exceptions.length; i++) {
if (i > 0)
System.out.print(", ");
System.out.print(typeName(exceptions[i]));
}
System.out.println(";");
}
}
Class Reflection: class modifier
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies. Please refer to
* the file "copyright.html" for further important copyright and licensing
* information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES.
*/
import java.lang.reflect.Modifier;
public class SampleModifier {
public static void main(String[] args) {
String s = new String();
printModifiers(s);
}
public static void printModifiers(Object o) {
Class c = o.getClass();
int m = c.getModifiers();
if (Modifier.isPublic(m))
System.out.println("public");
if (Modifier.isAbstract(m))
System.out.println("abstract");
if (Modifier.isFinal(m))
System.out.println("final");
}
}
Class Reflection: class name
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies. Please refer to
* the file "copyright.html" for further important copyright and licensing
* information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES.
*/
import java.awt.Button;
public class SampleName {
public static void main(String[] args) {
Button b = new Button();
;
printName(b);
}
static void printName(Object o) {
Class c = o.getClass();
String s = c.getName();
System.out.println(s);
}
}
Class Reflection: name for super class
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for NON-COMMERCIAL purposes and without fee is hereby granted
* provided that this copyright notice appears in all copies. Please refer to
* the file "copyright.html" for further important copyright and licensing
* information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
* NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES.
*/
import java.awt.Button;
public class SampleSuper {
public static void main(String[] args) {
Button b = new Button();
printSuperclasses(b);
}
static void printSuperclasses(Object o) {
Class subclass = o.getClass();
Class superclass = subclass.getSuperclass();
while (superclass != null) {
String className = superclass.getName();
System.out.println(className);
subclass = superclass;
superclass = subclass.getSuperclass();
}
}
}
Convert a given String into the appropriate Class.
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
public class Main {
/** Primitive type name -> class map. */
private static final Map PRIMITIVE_NAME_TYPE_MAP = new HashMap();
/** Setup the primitives map. */
static {
PRIMITIVE_NAME_TYPE_MAP.put("boolean", Boolean.TYPE);
PRIMITIVE_NAME_TYPE_MAP.put("byte", Byte.TYPE);
PRIMITIVE_NAME_TYPE_MAP.put("char", Character.TYPE);
PRIMITIVE_NAME_TYPE_MAP.put("short", Short.TYPE);
PRIMITIVE_NAME_TYPE_MAP.put("int", Integer.TYPE);
PRIMITIVE_NAME_TYPE_MAP.put("long", Long.TYPE);
PRIMITIVE_NAME_TYPE_MAP.put("float", Float.TYPE);
PRIMITIVE_NAME_TYPE_MAP.put("double", Double.TYPE);
}
/**
* Convert a list of Strings from an Interator into an array of Classes (the
* Strings are taken as classnames).
*
* @param it
* A java.util.Iterator pointing to a Collection of Strings
* @param cl
* The ClassLoader to use
*
* @return Array of Classes
*
* @throws ClassNotFoundException
* When a class could not be loaded from the specified ClassLoader
*/
public final static Class<?>[] convertToJavaClasses(Iterator<String> it, ClassLoader cl)
throws ClassNotFoundException {
ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
while (it.hasNext()) {
classes.add(convertToJavaClass(it.next(), cl));
}
return classes.toArray(new Class[classes.size()]);
}
/**
* Convert a given String into the appropriate Class.
*
* @param name
* Name of class
* @param cl
* ClassLoader to use
*
* @return The class for the given name
*
* @throws ClassNotFoundException
* When the class could not be found by the specified ClassLoader
*/
private final static Class convertToJavaClass(String name, ClassLoader cl)
throws ClassNotFoundException {
int arraySize = 0;
while (name.endsWith("[]")) {
name = name.substring(0, name.length() - 2);
arraySize++;
}
// Check for a primitive type
Class c = (Class) PRIMITIVE_NAME_TYPE_MAP.get(name);
if (c == null) {
// No primitive, try to load it from the given ClassLoader
try {
c = cl.loadClass(name);
} catch (ClassNotFoundException cnfe) {
throw new ClassNotFoundException("Parameter class not found: " + name);
}
}
// if we have an array get the array class
if (arraySize > 0) {
int[] dims = new int[arraySize];
for (int i = 0; i < arraySize; i++) {
dims[i] = 1;
}
c = Array.newInstance(c, dims).getClass();
}
return c;
}
}
CrossRef prints a cross-reference about all classes named in argv
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ruparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
/**
* CrossRef prints a cross-reference about all classes named in argv.
* For each class, all public fields and methods are listed.
* "Reflectance" is used to look up the information.
*
* It is expected that the output will be post-processed e.g.,
* with sort and awk/perl. Try:
java CrossRef |
uniq | # squeeze out polymorphic forms early
sort | awk "$2=="method" { ... }" > crossref-methods.txt
* The part in "{ ... }" is left as an exercise for the reader. :-(
*
* @author Ian Darwin, Ian@DarwinSys.ru
* @version $Id: CrossRef.java,v 1.16 2003/04/08 20:01:44 ian Exp $
*/
public class CrossRef extends APIFormatter {
/** Simple main program, construct self, process each .ZIP file
* found in CLASSPATH or in argv.
*/
public static void main(String[] argv) throws IOException {
CrossRef xref = new CrossRef();
xref.doArgs(argv);
}
/**
* Print the fields and methods of one class.
*/
protected void doClass(Class c) {
int i, mods;
startClass(c);
try {
Field[] fields = c.getDeclaredFields();
Arrays.sort(fields, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Field)o1).getName().rupareTo(((Field)o2).getName());
}
});
for (i = 0; i < fields.length; i++) {
Field field = (Field)fields[i];
if (!Modifier.isPrivate(field.getModifiers()))
putField(field, c);
// else System.err.println("private field ignored: " + field);
}
Method methods[] = c.getDeclaredMethods();
// Arrays.sort(methods);
for (i = 0; i < methods.length; i++) {
if (!Modifier.isPrivate(methods[i].getModifiers()))
putMethod(methods[i], c);
// else System.err.println("pvt: " + methods[i]);
}
} catch (Exception e) {
e.printStackTrace();
}
endClass();
}
/** put a Field"s information to the standard output. */
protected void putField(Field fld, Class c) {
println(fld.getName() + " field " + c.getName() + " ");
}
/** put a Method"s information to the standard output. */
protected void putMethod(Method method, Class c) {
String methName = method.getName();
println(methName + " method " + c.getName() + " ");
}
/** Print the start of a class. Unused in this version,
* designed to be overridden */
protected void startClass(Class c) {
}
/** Print the end of a class. Unused in this version,
* designed to be overridden */
protected void endClass() {
}
/** Convenience routine, short for System.out.println */
protected final void println(String s) {
System.out.println(s);
}
}
/**
* <p>
* APIFormatter reads one or more Zip files, gets all entries from each
* and, for each entry that ends in ".class", loads it with Class.forName()
* and hands it off to a doClass(Class c) method declared in a subclass.
* <br/>TODO<br/>
* Use GETOPT to control doingStandardClasses, verbosity level, etc.
* @author Ian Darwin, Ian@DarwinSys.ru
* @version $Id: APIFormatter.java,v 1.6 2004/03/14 14:00:34 ian Exp $
*/
abstract class APIFormatter {
/** True if we are doing classpath, so only do java. and javax. */
protected static boolean doingStandardClasses = true;
protected int doArgs(String[] argv) throws IOException {
/** Counter of fields/methods printed. */
int n = 0;
// TODO: options
// -b - process bootclasspath
// -c - process classpath (default)
// -s - only process "java." and "javax."
if (argv.length == 0) {
// No arguments, look in CLASSPATH
String s = System.getProperty("java.class.path");
// break apart with path sep.
String pathSep = System.getProperty("path.separator");
StringTokenizer st = new StringTokenizer(s, pathSep);
// Process each zip in classpath
while (st.hasMoreTokens()) {
String thisFile = st.nextToken();
System.err.println("Trying path " + thisFile);
if (thisFile.endsWith(".zip") || thisFile.endsWith(".jar"))
processOneZip(thisFile);
}
} else {
// We have arguments, process them as zip/jar files
// doingStandardClasses = false;
for (int i=0; i<argv.length; i++)
processOneZip(argv[i]);
}
return n;
}
/** For each Zip file, for each entry, xref it */
public void processOneZip(String fileName) throws IOException {
List entries = new ArrayList();
ZipFile zipFile = null;
try {
zipFile = new ZipFile(new File(fileName));
} catch (ZipException zz) {
throw new FileNotFoundException(zz.toString() + fileName);
}
Enumeration all = zipFile.entries();
// Put the entries into the List for sorting...
while (all.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry)all.nextElement();
entries.add(zipEntry);
}
// Sort the entries (by class name)
// Collections.sort(entries);
// Process all the entries in this zip.
Iterator it = entries.iterator();
while (it.hasNext()) {
ZipEntry zipEntry = (ZipEntry)it.next();
String zipName = zipEntry.getName();
// Ignore package/directory, other odd-ball stuff.
if (zipEntry.isDirectory()) {
continue;
}
// Ignore META-INF stuff
if (zipName.startsWith("META-INF/")) {
continue;
}
// Ignore images, HTML, whatever else we find.
if (!zipName.endsWith(".class")) {
continue;
}
// If doing CLASSPATH, Ignore com.* which are "internal API".
// if (doingStandardClasses && !zipName.startsWith("java")){
// continue;
// }
// Convert the zip file entry name, like
// java/lang/Math.class
// to a class name like
// java.lang.Math
String className = zipName.replace("/", ".").
substring(0, zipName.length() - 6); // 6 for ".class"
// Now get the Class object for it.
Class c = null;
try {
c = Class.forName(className);
} catch (ClassNotFoundException ex) {
System.err.println("Error: " + ex);
}
// Hand it off to the subclass...
doClass(c);
}
}
/** Format the fields and methods of one class, given its name.
*/
protected abstract void doClass(Class c) throws IOException;
}
Demonstrate classFor to create an instance of an object
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.awt.Frame;
/** Demonstrate "classFor" to create an instance of an object. */
public class ClassForName {
public static void main(String[] av) {
Class c = null;
Object o = null;
try {
// Load the class, return a Class for it
c = Class.forName("java.awt.Frame");
// Construct an object, as if new Type()
o = c.newInstance();
} catch (Exception e) {
System.err
.println("That didn"t work. " + " Try something else" + e);
}
if (o != null && o instanceof Frame) {
Frame f = (Frame) o;
f.setTitle("Testing");
f.setVisible(true);
} else
throw new IllegalArgumentException("Huh? What gives?");
}
}
Demonstration of speed of reflexive versus programmatic invocation
/*
* file: ReflexiveInvocation.java
* package: oreilly.hcj.reflection
*
* This software is granted under the terms of the Common Public License,
* CPL, which may be found at the following URL:
* http://www-124.ibm.ru/developerworks/oss/CPLv1.0.htm
*
* Copyright(c) 2003-2005 by the authors indicated in the @author tags.
* All Rights are Reserved by the various authors.
*
########## DO NOT EDIT ABOVE THIS LINE ########## */
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Demonstration of speed of reflexive versus programatic invocation.
*
* @author
* @version $Revision: 1.3 $
*/
public class ReflexiveInvocation {
/** Holds value of property value. */
private String value = "some value";
/**
* Creates a new instance of ReflexiveInvocation
*/
public ReflexiveInvocation() {
}
/**
* Main demo method.
*
* @param args
* the command line arguments
*
* @throws RuntimeException
* __UNDOCUMENTED__
*/
public static void main(final String[] args) {
try {
final int CALL_AMOUNT = 1000000;
final ReflexiveInvocation ri = new ReflexiveInvocation();
int idx = 0;
// Call the method without using reflection.
long millis = System.currentTimeMillis();
for (idx = 0; idx < CALL_AMOUNT; idx++) {
ri.getValue();
}
System.out.println("Calling method " + CALL_AMOUNT + " times programatically took "
+ (System.currentTimeMillis() - millis) + " millis");
// Call while looking up the method in each iteration.
Method md = null;
millis = System.currentTimeMillis();
for (idx = 0; idx < CALL_AMOUNT; idx++) {
md = ri.getClass().getMethod("getValue", null);
md.invoke(ri, null);
}
System.out.println("Calling method " + CALL_AMOUNT + " times reflexively with lookup took "
+ (System.currentTimeMillis() - millis) + " millis");
// Call using a cache of the method.
md = ri.getClass().getMethod("getValue", null);
millis = System.currentTimeMillis();
for (idx = 0; idx < CALL_AMOUNT; idx++) {
md.invoke(ri, null);
}
System.out.println("Calling method " + CALL_AMOUNT + " times reflexively with cache took "
+ (System.currentTimeMillis() - millis) + " millis");
} catch (final NoSuchMethodException ex) {
throw new RuntimeException(ex);
} catch (final InvocationTargetException ex) {
throw new RuntimeException(ex);
} catch (final IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
/**
* Getter for property value.
*
* @return Value of property value.
*/
public String getValue() {
return this.value;
}
}
/* ########## End of File ########## */
Dump a class using Reflection
/*
* ReflectClass.java - Dump a class using Reflection.
*
* Copyright (c) 1997 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
* SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT
* OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
import java.lang.reflect.*;
import java.util.*;
public class ReflectClass {
static String tName(String nm, Hashtable ht) {
String yy;
String arr;
if (nm.charAt(0) != "[") {
int i = nm.lastIndexOf(".");
if (i == -1)
return nm; // It"s a primitive type, ignore it.
else {
yy = nm.substring(i+1);
if (ht != null)
ht.put(nm, yy); // note class types in the hashtable.
return yy;
}
}
arr = "[]";
if (nm.charAt(1) == "[")
yy = tName(nm.substring(1), ht);
else {
switch (nm.charAt(1)) {
case "L" :
yy = tName(nm.substring(nm.indexOf("L")+1, nm.indexOf(";")), ht);
break;
case "I":
yy = "int";
break;
case "V":
yy = "void";
break;
case "C":
yy = "char";
break;
case "D":
yy = "double";
break;
case "F":
yy = "float";
break;
case "J":
yy = "long";
break;
case "S":
yy = "short";
break;
case "Z":
yy = "boolean";
break;
case "B":
yy = "byte";
break;
default:
yy = "BOGUS:"+nm;
break;
}
}
return yy+arr;
}
public static void main(String args[]) {
Constructor cn[];
Class cc[];
Method mm[];
Field ff[];
Class c = null;
Class supClass;
String x, y, s1, s2, s3;
Hashtable classRef = new Hashtable();
if (args.length == 0) {
System.out.println("Please specify a class name on the command line.");
System.exit(1);
}
try {
c = Class.forName(args[0]);
} catch (ClassNotFoundException ee) {
System.out.println("Couldn"t find class ""+args[0]+""");
System.exit(1);
}
/*
* Step 0: If our name contains dots we"re in a package so put
* that out first.
*/
x = c.getName();
if (x.lastIndexOf(".") != -1) {
y = x.substring(0, x.lastIndexOf("."));
System.out.println("package "+y+";\n\r");
}
/*
* Let"s use the Reflection API to sift through what is
* inside this class.
*
* Step 1: Collect referenced classes
* This step is used so that I can regenerate the import statements.
* It isn"t strictly required of course, Java works just fine with
* fully qualified object class names, but it looks better when you
* use "String" rather than "java.lang.String" as the return type.
*/
ff = c.getDeclaredFields();
for (int i = 0; i < ff.length; i++) {
x = tName(ff[i].getType().getName(), classRef);
}
cn = c.getDeclaredConstructors();
for (int i = 0; i < cn.length; i++) {
Class cx[] = cn[i].getParameterTypes();
if (cx.length > 0) {
for (int j = 0; j < cx.length; j++) {
x = tName(cx[j].getName(), classRef);
}
}
}
mm = c.getDeclaredMethods();
for (int i = 0; i < mm.length; i++) {
x = tName(mm[i].getReturnType().getName(), classRef);
Class cx[] = mm[i].getParameterTypes();
if (cx.length > 0) {
for (int j = 0; j < cx.length; j++) {
x = tName(cx[j].getName(), classRef);
}
}
}
// Don"t import ourselves ...
classRef.remove(c.getName());
/*
* Step 2: Start class description generation, start by printing
* out the import statements.
*
* This is the line that goes "public SomeClass extends Foo {"
*/
for (Enumeration e = classRef.keys(); e.hasMoreElements(); ) {
System.out.println("import "+e.nextElement()+";");
}
System.out.println();
/*
* Step 3: Print the class or interface introducer. We use
* a convienience method in Modifer to print the whole string.
*/
int mod = c.getModifiers();
System.out.print(Modifier.toString(mod));
if (Modifier.isInterface(mod)) {
System.out.print(" interface ");
} else {
System.out.print(" class ");
}
System.out.print(tName(c.getName(), null));
supClass = c.getSuperclass();
if (supClass != null) {
System.out.print(" extends "+tName(supClass.getName(), classRef));
}
System.out.println(" {");
/*
* Step 4: Print out the fields (internal class members) that are declared
* by this class.
*
* Fields are of the form [Modifiers] [Type] [Name] ;
*/
System.out.println("\n\r/*\n\r * Field Definitions.\r\n */");
for (int i = 0; i < ff.length; i++) {
Class ctmp = ff[i].getType();
int md = ff[i].getModifiers();
System.out.println(" "+Modifier.toString(md)+" "+
tName(ff[i].getType().getName(), null) +" "+
ff[i].getName()+";");
}
/*
* Step 5: Print out the constructor declarations.
*
* We note the name of the class which is the "name" for all
* constructors. Also there is no type, so the definition is
* simplye [Modifiers] ClassName ( [ Parameters ] ) { }
*
*/
System.out.println("\n\r/*\n\r * Declared Constructors. \n\r */");
x = tName(c.getName(), null);
for (int i = 0; i < cn.length; i++) {
int md = cn[i].getModifiers();
System.out.print(" " + Modifier.toString(md) + " " + x);
Class cx[] = cn[i].getParameterTypes();
System.out.print("( ");
if (cx.length > 0) {
for (int j = 0; j < cx.length; j++) {
System.out.print(tName(cx[j].getName(), null));
if (j < (cx.length - 1)) System.out.print(", ");
}
}
System.out.print(") ");
System.out.println("{ ... }");
}
/*
* Step 6: Print out the method declarations.
*
* Now methods have a name, a return type, and an optional
* set of parameters so they are :
* [modifiers] [type] [name] ( [optional parameters] ) { }
*/
System.out.println("\n\r/*\n\r * Declared Methods.\n\r */");
for (int i = 0; i < mm.length; i++) {
int md = mm[i].getModifiers();
System.out.print(" "+Modifier.toString(md)+" "+
tName(mm[i].getReturnType().getName(), null)+" "+
mm[i].getName());
Class cx[] = mm[i].getParameterTypes();
System.out.print("( ");
if (cx.length > 0) {
for (int j = 0; j < cx.length; j++) {
System.out.print(tName(cx[j].getName(), classRef));
if (j < (cx.length - 1)) System.out.print(", ");
}
}
System.out.print(") ");
System.out.println("{ ... }");
}
/*
* Step 7: Print out the closing brace and we"re done!
*/
System.out.println("}");
}
}
Encapsulates a class serialVersionUID and codebase.
/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.ObjectStreamClass;
import java.io.Serializable;
import java.net.URL;
import java.security.CodeSource;
/**
* Encapsulates a class serialVersionUID and codebase.
*
* @author Scott.Stark@jboss.org
* @version $Revision: 81038 $
*/
public class ClassVersionInfo implements Serializable {
static final long serialVersionUID = 2036506209171911437L;
/** The named class serialVersionUID as returned by ObjectStreamClass */
private long serialVersion;
/** The binary class name */
private String name;
private boolean hasExplicitSerialVersionUID;
private transient URL location;
public ClassVersionInfo(String name, ClassLoader loader) throws ClassNotFoundException {
this.name = name;
Class c = loader.loadClass(name);
CodeSource cs = c.getProtectionDomain().getCodeSource();
if (cs != null)
location = cs.getLocation();
if (c.isInterface() == false) {
ObjectStreamClass osc = ObjectStreamClass.lookup(c);
if (osc != null) {
serialVersion = osc.getSerialVersionUID();
try {
c.getDeclaredField("serialVersionUID");
hasExplicitSerialVersionUID = true;
} catch (NoSuchFieldException e) {
hasExplicitSerialVersionUID = false;
}
}
}
}
public long getSerialVersion() {
return serialVersion;
}
public boolean getHasExplicitSerialVersionUID() {
return hasExplicitSerialVersionUID;
}
public String getName() {
return name;
}
public String toString() {
StringBuffer tmp = new StringBuffer("ClassVersionInfo");
tmp.append("{");
tmp.append("serialVersion=");
tmp.append(serialVersion);
tmp.append(", hasExplicitSerialVersionUID=");
tmp.append(hasExplicitSerialVersionUID);
tmp.append(", name=");
tmp.append(name);
tmp.append(", location=");
tmp.append(location);
tmp.append("}");
return tmp.toString();
}
/**
* Usage: ClassVersionInfo class-name
*
* Locate the class name on the thread context class loader classpath and
* print its version info.
*
* @param args
* [0] = class-name
*/
public static void main(String[] args) throws Exception {
if (args.length == 0)
throw new IllegalStateException("Usage: ...ClassVersionInfo class-name");
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ClassVersionInfo info = new ClassVersionInfo(args[0], loader);
System.out.println(info);
}
}
Get the class By way of a string
public class Main {
public static void main(String[] argv) throws Exception {
Object object = new String();
try {
Class cls = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
}
}
}
Get the class By way of .class
public class Main {
public static void main(String[] argv) throws Exception {
Object object = new String();
Class cls = java.lang.String.class;
}
}
JavaP prints structural information about classes
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* JavaP prints structural information about classes. For each class, all public
* fields and methods are listed. The "Reflection" API is used to look up the
* information.
*
* @version $Id: MyJavaP.java,v 1.6 2004/03/14 17:45:51 ian Exp $
*/
public class MyJavaP {
/**
* Simple main program, construct self, process each class name found in
* argv.
*/
public static void main(String[] argv) {
MyJavaP pp = new MyJavaP();
if (argv.length == 0) {
System.err.println("Usage: MyJavaP className [...]");
System.exit(1);
} else
for (int i = 0; i < argv.length; i++)
pp.doClass(argv[i]);
}
/**
* Format the fields and methods of one class, given its name.
*/
protected void doClass(String className) {
try {
Class c = Class.forName(className);
System.out.println(Modifier.toString(c.getModifiers()) + " " + c
+ " {");
int mods;
Field fields[] = c.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (!Modifier.isPrivate(fields[i].getModifiers())
&& !Modifier.isProtected(fields[i].getModifiers()))
System.out.println("\t" + fields[i]);
}
Constructor[] constructors = c.getConstructors();
for (int j = 0; j < constructors.length; j++) {
Constructor constructor = constructors[j];
System.out.println("\t" + constructor);
}
Method methods[] = c.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (!Modifier.isPrivate(methods[i].getModifiers())
&& !Modifier.isProtected(methods[i].getModifiers()))
System.out.println("\t" + methods[i]);
}
System.out.println("}");
} catch (ClassNotFoundException e) {
System.err.println("Error: Class " + className + " not found!");
} catch (Exception e) {
System.err.println(e);
}
}
}
Load the class source location from Class.getResource()
public class Main {
public static void main(String args[]) {
Class theClass = Main.class;
java.net.URL u = theClass.getResource("");
System.out.println("This class (FromWhere) is located at : " + u);
}
}
Make up a compilable version of a given Sun or other API
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
/** Make up a compilable version of a given Sun or other API,
* so developers can compile against it without a licensed copy. In Sun"s case,
* all public API info is public on Sun"s web site, so this does not disclose
* anything that is Sun Confidential.
* <p>This is a clean-room implementation: I did not look at the code
* for Sun"s javap or any similar tool in preparing this program.
* XXX TODO:<ul>
* <li>Class printing: add superclasses.
* <li>Collapse common code in printing Constructors and Methods
* <li>Method printing: add exceptions
* <li>Arguments: Handle arrays (names begin [L)
* <li>Provide default (0, false, null) based on type; use in return statements
* and in assigment to protected final variables.
* </ul>
* @author Ian Darwin, http://www.darwinsys.ru/
* @version $Id: RevEngAPI.java,v 1.11 2004/05/30 01:43:43 ian Exp $
*/
public class RevEngAPI extends APIFormatter {
public static void main(String[] argv) throws Exception {
new RevEngAPI().doArgs(argv);
}
private final static String PREFIX_ARG = "arg";
/** Make up names like "arg0" "arg1", etc. */
private String mkName(String name, int number) {
return new StringBuffer(name).append(number).toString();
}
/** NOT THREAD SAFE */
private String className;
private int classNameOffset;
/** Generate a .java file for the outline of the given class. */
public void doClass(Class c) throws IOException {
className = c.getName();
// pre-compute offset for stripping package name
classNameOffset = className.lastIndexOf(".") + 1;
// Inner class
if (className.indexOf("$") != -1)
return;
// get name, as String, with . changed to /
String slashName = className.replace(".","/");
String fileName = slashName + ".java";
System.out.println(className + " --> " + fileName);
String dirName = slashName.substring(0, slashName.lastIndexOf("/"));
new File(dirName).mkdirs();
// create the file.
PrintWriter out = new PrintWriter(new FileWriter(fileName));
out.println("// Generated by RevEngAPI for class " + className);
// If in a package, say so.
Package pkg;
if ((pkg = c.getPackage()) != null) {
out.println("package " + pkg.getName() + ";");
out.println();
}
// print class header
int cMods = c.getModifiers();
printMods(cMods, out);
out.print("class ");
out.print(trim(c.getName()));
out.print(" ");
// XXX get superclass
out.println("{");
// print constructors
Constructor[] ctors = c.getDeclaredConstructors();
for (int i=0; i< ctors.length; i++) {
if (i == 0) {
out.println();
out.println("\t// Constructors");
}
Constructor cons = ctors[i];
int mods = cons.getModifiers();
if (Modifier.isPrivate(mods))
continue;
out.print("\t");
printMods(mods, out);
out.print(trim(cons.getName()) + "(");
Class[] classes = cons.getParameterTypes();
for (int j = 0; j<classes.length; j++) {
if (j > 0) out.print(", ");
out.print(trim(classes[j].getName()) + " " +
mkName(PREFIX_ARG, j));
}
out.println(") {");
out.print("\t}");
}
// print method names
Method[] mems = c.getDeclaredMethods();
for (int i=0; i< mems.length; i++) {
if (i == 0) {
out.println();
out.println("\t// Methods");
}
Method m = mems[i];
if (m.getName().startsWith("access$"))
continue;
int mods = m.getModifiers();
if (Modifier.isPrivate(mods))
continue;
out.print("\t");
printMods(mods, out);
out.print(m.getReturnType());
out.print(" ");
out.print(trim(m.getName()) + "(");
Class[] classes = m.getParameterTypes();
for (int j = 0; j<classes.length; j++) {
if (j > 0) out.print(", ");
out.print(trim(classes[j].getName()) + " " +
mkName(PREFIX_ARG, j));
}
out.println(") {");
out.println("\treturn " + defaultValue(m.getReturnType()) + ";");
out.println("\t}");
}
// print fields
Field[] flds = c.getDeclaredFields();
for (int i=0; i< flds.length; i++) {
if (i == 0) {
out.println();
out.println("\t// Fields");
}
Field f = flds[i];
int mods = f.getModifiers();
if (Modifier.isPrivate(mods))
continue;
out.print("\t");
printMods(mods, out);
out.print(trim(f.getType().getName()));
out.print(" ");
out.print(f.getName());
if (Modifier.isFinal(mods)) {
try {
out.print(" = " + f.get(null));
} catch (IllegalAccessException ex) {
out.print("; // " + ex.toString());
}
}
out.println(";");
}
out.println("}");
//out.flush();
out.close();
}
private String trim(String theName) {
return theName.startsWith(className) ?
theName.substring(classNameOffset) : theName;
}
private class ModInfo {
int val;
String name;
ModInfo(int v, String n) {
val = v;
name = n;
}
}
private ModInfo[] modInfo = {
new ModInfo(16, "final"),
new ModInfo(2, "private"),
new ModInfo(1, "public"),
new ModInfo(4, "protected"),
new ModInfo(1024, "abstract"),
new ModInfo(8, "static"),
new ModInfo(32, "synchronized"),
new ModInfo(256, "native"),
new ModInfo(128, "transient"),
new ModInfo(64, "volatile"),
new ModInfo(2048, "strict"),
};
private void printMods(int mods, PrintWriter out) {
for (int i=0; i < modInfo.length; i++) {
if ((mods & modInfo[i].val) == modInfo[i].val) {
out.print(modInfo[i].name);
out.print(" ");
}
}
}
private String defaultValue(Class c) {
if (c.getName().equals("boolean"))
return "false";
// XXX else if object type return null;
else return "0";
}
public void startFile() {
// XXX save filename as project name
}
public void endFile() {
// XXX generate a trivial "build.xml" for Ant to create the jar file.
}
}
/**
* <p>
* APIFormatter reads one or more Zip files, gets all entries from each
* and, for each entry that ends in ".class", loads it with Class.forName()
* and hands it off to a doClass(Class c) method declared in a subclass.
* <br/>TODO<br/>
* Use GETOPT to control doingStandardClasses, verbosity level, etc.
* @author Ian Darwin, Ian@DarwinSys.ru
* @version $Id: APIFormatter.java,v 1.6 2004/03/14 14:00:34 ian Exp $
*/
abstract class APIFormatter {
/** True if we are doing classpath, so only do java. and javax. */
protected static boolean doingStandardClasses = true;
protected int doArgs(String[] argv) throws IOException {
/** Counter of fields/methods printed. */
int n = 0;
// TODO: options
// -b - process bootclasspath
// -c - process classpath (default)
// -s - only process "java." and "javax."
if (argv.length == 0) {
// No arguments, look in CLASSPATH
String s = System.getProperty("java.class.path");
// break apart with path sep.
String pathSep = System.getProperty("path.separator");
StringTokenizer st = new StringTokenizer(s, pathSep);
// Process each zip in classpath
while (st.hasMoreTokens()) {
String thisFile = st.nextToken();
System.err.println("Trying path " + thisFile);
if (thisFile.endsWith(".zip") || thisFile.endsWith(".jar"))
processOneZip(thisFile);
}
} else {
// We have arguments, process them as zip/jar files
// doingStandardClasses = false;
for (int i=0; i<argv.length; i++)
processOneZip(argv[i]);
}
return n;
}
/** For each Zip file, for each entry, xref it */
public void processOneZip(String fileName) throws IOException {
List entries = new ArrayList();
ZipFile zipFile = null;
try {
zipFile = new ZipFile(new File(fileName));
} catch (ZipException zz) {
throw new FileNotFoundException(zz.toString() + fileName);
}
Enumeration all = zipFile.entries();
// Put the entries into the List for sorting...
while (all.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry)all.nextElement();
entries.add(zipEntry);
}
// Sort the entries (by class name)
// Collections.sort(entries);
// Process all the entries in this zip.
Iterator it = entries.iterator();
while (it.hasNext()) {
ZipEntry zipEntry = (ZipEntry)it.next();
String zipName = zipEntry.getName();
// Ignore package/directory, other odd-ball stuff.
if (zipEntry.isDirectory()) {
continue;
}
// Ignore META-INF stuff
if (zipName.startsWith("META-INF/")) {
continue;
}
// Ignore images, HTML, whatever else we find.
if (!zipName.endsWith(".class")) {
continue;
}
// If doing CLASSPATH, Ignore com.* which are "internal API".
// if (doingStandardClasses && !zipName.startsWith("java")){
// continue;
// }
// Convert the zip file entry name, like
// java/lang/Math.class
// to a class name like
// java.lang.Math
String className = zipName.replace("/", ".").
substring(0, zipName.length() - 6); // 6 for ".class"
// Now get the Class object for it.
Class c = null;
try {
c = Class.forName(className);
} catch (ClassNotFoundException ex) {
System.err.println("Error: " + ex);
}
// Hand it off to the subclass...
doClass(c);
}
}
/** Format the fields and methods of one class, given its name.
*/
protected abstract void doClass(Class c) throws IOException;
}
Manipulate Java classes
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This class contains utility methods to manipulate Java classes.
*
* @author
* @version $Id: ClassFileUtilities.java 599691 2007-11-30 03:37:58Z cam $
*/
public class ClassFileUtilities {
// Constant pool info tags
public static final byte CONSTANT_UTF8_INFO = 1;
public static final byte CONSTANT_INTEGER_INFO = 3;
public static final byte CONSTANT_FLOAT_INFO = 4;
public static final byte CONSTANT_LONG_INFO = 5;
public static final byte CONSTANT_DOUBLE_INFO = 6;
public static final byte CONSTANT_CLASS_INFO = 7;
public static final byte CONSTANT_STRING_INFO = 8;
public static final byte CONSTANT_FIELDREF_INFO = 9;
public static final byte CONSTANT_METHODREF_INFO = 10;
public static final byte CONSTANT_INTERFACEMETHODREF_INFO = 11;
public static final byte CONSTANT_NAMEANDTYPE_INFO = 12;
/**
* This class does not need to be instantiated.
*/
protected ClassFileUtilities() {
}
/**
* Program that computes the dependencies between the Batik jars.
* <p>
* Run this from the main Batik distribution directory, after building
* the jars. For every jar file in the batik-xxx/ build directory,
* it will determine which other jar files it directly depends on.
* The output is lines of the form:
* </p>
* <pre> <i>number</i>,<i>from</i>,<i>to</i></pre>
* <p>
* where mean that the <i>from</i> jar has <i>number</i> class files
* that depend on class files in the <i>to</i> jar.
* </p>
*/
public static void main(String[] args) {
boolean showFiles = false;
if (args.length == 1 && args[0].equals("-f")) {
showFiles = true;
} else if (args.length != 0) {
System.err.println("usage: ClassFileUtilities [-f]");
System.err.println();
System.err.println(" -f list files that cause each jar file dependency");
System.exit(1);
}
File cwd = new File(".");
File buildDir = null;
String[] cwdFiles = cwd.list();
for (int i = 0; i < cwdFiles.length; i++) {
if (cwdFiles[i].startsWith("batik-")) {
buildDir = new File(cwdFiles[i]);
if (!buildDir.isDirectory()) {
buildDir = null;
} else {
break;
}
}
}
if (buildDir == null || !buildDir.isDirectory()) {
System.out.println("Directory "batik-xxx" not found in current directory!");
return;
}
try {
Map cs = new HashMap();
Map js = new HashMap();
collectJars(buildDir, js, cs);
Set classpath = new HashSet();
Iterator i = js.values().iterator();
while (i.hasNext()) {
classpath.add(((Jar) i.next()).jarFile);
}
i = cs.values().iterator();
while (i.hasNext()) {
ClassFile fromFile = (ClassFile) i.next();
// System.out.println(fromFile.name);
Set result = getClassDependencies(fromFile.getInputStream(),
classpath, false);
Iterator j = result.iterator();
while (j.hasNext()) {
ClassFile toFile = (ClassFile) cs.get(j.next());
if (fromFile != toFile && toFile != null) {
fromFile.deps.add(toFile);
}
}
}
i = cs.values().iterator();
while (i.hasNext()) {
ClassFile fromFile = (ClassFile) i.next();
Iterator j = fromFile.deps.iterator();
while (j.hasNext()) {
ClassFile toFile = (ClassFile) j.next();
Jar fromJar = fromFile.jar;
Jar toJar = toFile.jar;
if (fromFile.name.equals(toFile.name)
|| toJar == fromJar
|| fromJar.files.contains(toFile.name)) {
continue;
}
Integer n = (Integer) fromJar.deps.get(toJar);
if (n == null) {
fromJar.deps.put(toJar, new Integer(1));
} else {
fromJar.deps.put(toJar, new Integer(n.intValue() + 1));
}
}
}
List triples = new ArrayList(10);
i = js.values().iterator();
while (i.hasNext()) {
Jar fromJar = (Jar) i.next();
Iterator j = fromJar.deps.keySet().iterator();
while (j.hasNext()) {
Jar toJar = (Jar) j.next();
Triple t = new Triple();
t.from = fromJar;
t.to = toJar;
t.count = ((Integer) fromJar.deps.get(toJar)).intValue();
triples.add(t);
}
}
Collections.sort(triples);
i = triples.iterator();
while (i.hasNext()) {
Triple t = (Triple) i.next();
System.out.println
(t.count + "," + t.from.name + "," + t.to.name);
if (showFiles) {
Iterator j = t.from.files.iterator();
while (j.hasNext()) {
ClassFile fromFile = (ClassFile) j.next();
Iterator k = fromFile.deps.iterator();
while (k.hasNext()) {
ClassFile toFile = (ClassFile) k.next();
if (toFile.jar == t.to
&& !t.from.files.contains(toFile.name)) {
System.out.println
("\t" + fromFile.name + " --> "
+ toFile.name);
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
protected static class ClassFile {
public String name;
public List deps = new ArrayList(10);
public Jar jar;
public InputStream getInputStream() throws IOException {
return jar.jarFile.getInputStream(jar.jarFile.getEntry(name));
}
}
protected static class Jar {
public String name;
public File file;
public JarFile jarFile;
public Map deps = new HashMap();
public Set files = new HashSet();
}
protected static class Triple implements Comparable {
public Jar from;
public Jar to;
public int count;
public int compareTo(Object o) {
return ((Triple) o).count - count;
}
}
private static void collectJars(File dir, Map jars, Map classFiles) throws IOException {
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
String n = files[i].getName();
if (n.endsWith(".jar") && files[i].isFile()) {
Jar j = new Jar();
j.name = files[i].getPath();
j.file = files[i];
j.jarFile = new JarFile(files[i]);
jars.put(j.name, j);
Enumeration entries = j.jarFile.entries();
while (entries.hasMoreElements()) {
ZipEntry ze = (ZipEntry) entries.nextElement();
String name = ze.getName();
if (name.endsWith(".class")) {
ClassFile cf = new ClassFile();
cf.name = name;
cf.jar = j;
classFiles.put(j.name + "!" + cf.name, cf);
j.files.add(cf);
}
}
} else if (files[i].isDirectory()) {
collectJars(files[i], jars, classFiles);
}
}
}
/**
* Returns the dependencies of the given class.
* @param path The root class path.
* @param classpath The set of directories (Strings) to scan.
* @param rec Whether to follow dependencies recursively.
* @return a list of paths representing the used classes.
*/
public static Set getClassDependencies(String path,
Set classpath,
boolean rec)
throws IOException {
return getClassDependencies(new FileInputStream(path), classpath, rec);
}
public static Set getClassDependencies(InputStream is,
Set classpath,
boolean rec)
throws IOException {
Set result = new HashSet();
Set done = new HashSet();
computeClassDependencies(is, classpath, done, result, rec);
return result;
}
private static void computeClassDependencies(InputStream is,
Set classpath,
Set done,
Set result,
boolean rec)
throws IOException {
Iterator it = getClassDependencies(is).iterator();
while (it.hasNext()) {
String s = (String)it.next();
if (!done.contains(s)) {
done.add(s);
Iterator cpit = classpath.iterator();
while (cpit.hasNext()) {
InputStream depis = null;
String path = null;
Object cpEntry = cpit.next();
if (cpEntry instanceof JarFile) {
JarFile jarFile = (JarFile) cpEntry;
String classFileName = s + ".class";
ZipEntry ze = jarFile.getEntry(classFileName);
if (ze != null) {
path = jarFile.getName() + "!" + classFileName;
depis = jarFile.getInputStream(ze);
}
} else {
path = ((String) cpEntry) + "/" + s + ".class";
File f = new File(path);
if (f.isFile()) {
depis = new FileInputStream(f);
}
}
if (depis != null) {
result.add(path);
if (rec) {
computeClassDependencies
(depis, classpath, done, result, rec);
}
}
}
}
}
}
/**
* Returns the dependencies of the given class.
* @return a list of strings representing the used classes.
*/
public static Set getClassDependencies(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
if (dis.readInt() != 0xcafebabe) {
throw new IOException("Invalid classfile");
}
dis.readInt();
int len = dis.readShort();
String[] strs = new String[len];
Set classes = new HashSet();
Set desc = new HashSet();
for (int i = 1; i < len; i++) {
int constCode = dis.readByte() & 0xff;
switch ( constCode ) {
case CONSTANT_LONG_INFO:
case CONSTANT_DOUBLE_INFO:
dis.readLong();
i++;
break;
case CONSTANT_FIELDREF_INFO:
case CONSTANT_METHODREF_INFO:
case CONSTANT_INTERFACEMETHODREF_INFO:
case CONSTANT_INTEGER_INFO:
case CONSTANT_FLOAT_INFO:
dis.readInt();
break;
case CONSTANT_CLASS_INFO:
classes.add(new Integer(dis.readShort() & 0xffff));
break;
case CONSTANT_STRING_INFO:
dis.readShort();
break;
case CONSTANT_NAMEANDTYPE_INFO:
dis.readShort();
desc.add(new Integer(dis.readShort() & 0xffff));
break;
case CONSTANT_UTF8_INFO:
strs[i] = dis.readUTF();
break;
default:
throw new RuntimeException("unexpected data in constant-pool:" + constCode );
}
}
Set result = new HashSet();
Iterator it = classes.iterator();
while (it.hasNext()) {
result.add(strs[((Integer)it.next()).intValue()]);
}
it = desc.iterator();
while (it.hasNext()) {
result.addAll(getDescriptorClasses(strs[((Integer)it.next()).intValue()]));
}
return result;
}
/**
* Returns the classes contained in a field or method desciptor.
*/
protected static Set getDescriptorClasses(String desc) {
Set result = new HashSet();
int i = 0;
char c = desc.charAt(i);
switch (c) {
case "(":
loop: for (;;) {
c = desc.charAt(++i);
switch (c) {
case "[":
do {
c = desc.charAt(++i);
} while (c == "[");
if (c != "L") {
break;
}
case "L":
c = desc.charAt(++i);
StringBuffer sb = new StringBuffer();
while (c != ";") {
sb.append(c);
c = desc.charAt(++i);
}
result.add(sb.toString());
break;
default:
break;
case ")":
break loop;
}
}
c = desc.charAt(++i);
switch (c) {
case "[":
do {
c = desc.charAt(++i);
} while (c == "[");
if (c != "L") {
break;
}
case "L":
c = desc.charAt(++i);
StringBuffer sb = new StringBuffer();
while (c != ";") {
sb.append(c);
c = desc.charAt(++i);
}
result.add(sb.toString());
break;
default:
case "V":
}
break;
case "[":
do {
c = desc.charAt(++i);
} while (c == "[");
if (c != "L") {
break;
}
case "L":
c = desc.charAt(++i);
StringBuffer sb = new StringBuffer();
while (c != ";") {
sb.append(c);
c = desc.charAt(++i);
}
result.add(sb.toString());
break;
default:
}
return result;
}
}
Manipulate Java class files in strange and mysterious ways
/*
* ClassFile.java Chuck McManis
*
* Copyright (c) 1996 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
* MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
/**
* This class is used to manipulate Java class files in strange and
* mysterious ways.
*
* Usage it typically to feed it an array of bytes that are a class
* file, manipulate the class, then convert the class back into bytes,
* and feed the final result to <TT>defineClass()</TT>.
*
* @version 1.6, 19 Aug 1995
* @author Chuck McManis
* @see AttributeInfo
* @see ConstantPoolInfo
* @see MethodInfo
* @see FieldInfo
*/
public class ClassFile {
int magic;
short majorVersion;
short minorVersion;
ConstantPoolInfo constantPool[];
short accessFlags;
ConstantPoolInfo thisClass;
ConstantPoolInfo superClass;
ConstantPoolInfo interfaces[];
FieldInfo fields[];
MethodInfo methods[];
AttributeInfo attributes[];
boolean isValidClass = false;
public static final int ACC_PUBLIC = 0x1;
public static final int ACC_PRIVATE = 0x2;
public static final int ACC_PROTECTED = 0x4;
public static final int ACC_STATIC = 0x8;
public static final int ACC_FINAL = 0x10;
public static final int ACC_SYNCHRONIZED = 0x20;
public static final int ACC_THREADSAFE = 0x40;
public static final int ACC_TRANSIENT = 0x80;
public static final int ACC_NATIVE = 0x100;
public static final int ACC_INTERFACE = 0x200;
public static final int ACC_ABSTRACT = 0x400;
public boolean debug = false;
public boolean dumpConstants = false;
/**
* Read a class from InputStream <i>in</i>.
*/
public boolean read(InputStream in)
throws IOException {
DataInputStream di = new DataInputStream(in);
int count;
magic = di.readInt();
if (magic != (int) 0xCAFEBABE) {
return (false);
}
majorVersion = di.readShort();
minorVersion = di.readShort();
count = di.readShort();
constantPool = new ConstantPoolInfo[count];
if (debug)
System.out.println("read(): Read header...");
constantPool[0] = new ConstantPoolInfo();
for (int i = 1; i < constantPool.length; i++) {
constantPool[i] = new ConstantPoolInfo();
if (! constantPool[i].read(di)) {
return (false);
}
// These two types take up "two" spots in the table
if ((constantPool[i].type == ConstantPoolInfo.LONG) ||
(constantPool[i].type == ConstantPoolInfo.DOUBLE))
i++;
}
/*
* Update pointers in the constant table. This turns the
* table into a real datastructure.
*
* TODO: Have it verify that the right arguments are present
*/
for (int i = 1; i < constantPool.length; i++) {
if (constantPool[i] == null)
continue;
if (constantPool[i].index1 > 0)
constantPool[i].arg1 = constantPool[constantPool[i].index1];
if (constantPool[i].index2 > 0)
constantPool[i].arg2 = constantPool[constantPool[i].index2];
}
if (dumpConstants) {
for (int i = 1; i < constantPool.length; i++) {
System.out.println("C"+i+" - "+constantPool[i]);
}
}
accessFlags = di.readShort();
thisClass = constantPool[di.readShort()];
superClass = constantPool[di.readShort()];
if (debug)
System.out.println("read(): Read class info...");
/*
* Identify all of the interfaces implemented by this class
*/
count = di.readShort();
if (count != 0) {
if (debug)
System.out.println("Class implements "+count+" interfaces.");
interfaces = new ConstantPoolInfo[count];
for (int i = 0; i < count; i++) {
int iindex = di.readShort();
if ((iindex < 1) || (iindex > constantPool.length - 1))
return (false);
interfaces[i] = constantPool[iindex];
if (debug)
System.out.println("I"+i+": "+interfaces[i]);
}
}
if (debug)
System.out.println("read(): Read interface info...");
/*
* Identify all fields in this class.
*/
count = di.readShort();
if (debug)
System.out.println("This class has "+count+" fields.");
if (count != 0) {
fields = new FieldInfo[count];
for (int i = 0; i < count; i++) {
fields[i] = new FieldInfo();
if (! fields[i].read(di, constantPool)) {
return (false);
}
if (debug)
System.out.println("F"+i+": "+
fields[i].toString(constantPool));
}
}
if (debug)
System.out.println("read(): Read field info...");
/*
* Identify all the methods in this class.
*/
count = di.readShort();
if (count != 0) {
methods = new MethodInfo[count];
for (int i = 0; i < count; i++) {
methods[i] = new MethodInfo();
if (! methods[i].read(di, constantPool)) {
return (false);
}
if (debug)
System.out.println("M"+i+": "+methods[i].toString());
}
}
if (debug)
System.out.println("read(): Read method info...");
/*
* Identify all of the attributes in this class
*/
count = di.readShort();
if (count != 0) {
attributes = new AttributeInfo[count];
for (int i = 0; i < count; i++) {
attributes[i] = new AttributeInfo();
if (! attributes[i].read(di, constantPool)) {
return (false);
}
}
}
if (debug) {
System.out.println("read(): Read attribute info...");
System.out.println("done.");
}
isValidClass = true;
return(true);
}
/**
* Write the class out as a stream of bytes to the output
* stream.
*
* Generally you will read a class file, manipulate
* it in some way, and then write it out again before passing
* it to <TT>defineClass</TT> in some class loader.
*/
public void write(OutputStream out)
throws IOException, Exception {
DataOutputStream dos = new DataOutputStream(out);
if (! isValidClass) {
throw new Exception("ClassFile::write() - Invalid Class");
}
dos.writeInt(magic);
dos.writeShort(majorVersion);
dos.writeShort(minorVersion);
dos.writeShort(constantPool.length);
for (int i = 1; i < constantPool.length; i++) {
if (constantPool[i] != null)
constantPool[i].write(dos, constantPool);
}
dos.writeShort(accessFlags);
dos.writeShort(ConstantPoolInfo.indexOf(thisClass, constantPool));
dos.writeShort(ConstantPoolInfo.indexOf(superClass, constantPool));
if (interfaces == null) {
dos.writeShort(0);
} else {
dos.writeShort(interfaces.length);
for (int i = 0; i < interfaces.length; i++) {
dos.writeShort(ConstantPoolInfo.indexOf(interfaces[i],
constantPool));
}
}
if (fields == null) {
dos.writeShort(0);
} else {
dos.writeShort(fields.length);
for (int i = 0; i < fields.length; i++) {
fields[i].write(dos, constantPool);
}
}
if (methods == null) {
dos.writeShort(0);
} else {
dos.writeShort(methods.length);
for (int i = 0; i < methods.length; i++) {
methods[i].write(dos, constantPool);
}
}
if (attributes == null) {
dos.writeShort(0);
} else {
dos.writeShort(attributes.length);
for (int i = 0; i < attributes.length; i++) {
attributes[i].write(dos, constantPool);
}
}
}
/**
* Returns a string that represents what the access flags
* are set for. So 0x14 returns "public final "
*/
public static String accessString(short flags) {
StringBuffer x = new StringBuffer();
if ((flags & ACC_PUBLIC) != 0) {
x.append("public ");
}
if ((flags & ACC_PRIVATE) != 0) {
x.append("private ");
}
if ((flags & ACC_PROTECTED) != 0) {
x.append("protected ");
}
if ((flags & ACC_STATIC) != 0) {
x.append("static ");
}
if ((flags & ACC_FINAL) != 0) {
x.append("final ");
}
if ((flags & ACC_SYNCHRONIZED) != 0) {
x.append("synchronized ");
}
if ((flags & ACC_THREADSAFE) != 0) {
x.append("threadsafe ");
}
if ((flags & ACC_TRANSIENT) != 0) {
x.append("transient ");
}
if ((flags & ACC_NATIVE) != 0) {
x.append("native ");
}
if ((flags & ACC_INTERFACE) != 0) {
x.append("interface ");
}
if ((flags & ACC_ABSTRACT) != 0) {
x.append("abstract ");
}
return (x.toString());
}
/**
* Takes a type signature and a string representing a variable name
* and returns a declaration for that variable name.
*
* For example, passing this the strings "[B" and "myArray" will
* return the string "byte myArray[]"
*/
public static String typeString(String typeString, String varName) {
int isArray = 0;
int ndx = 0;
StringBuffer x = new StringBuffer();
while (typeString.charAt(ndx) == "[") {
isArray++;
ndx++;
}
switch (typeString.charAt(ndx)) {
case "B" :
x.append("byte ");
break;
case "C" :
x.append("char ");
break;
case "D" :
x.append("double ");
break;
case "F" :
x.append("float ");
break;
case "I" :
x.append("int ");
break;
case "J" :
x.append("long ");
break;
case "L" :
for (int i = ndx+1; i < typeString.indexOf(";"); i++) {
if (typeString.charAt(i) != "/")
x.append(typeString.charAt(i));
else
x.append(".");
}
x.append(" ");
break;
case "V":
x.append("void ");
break;
case "S" :
x.append("short ");
break;
case "Z" :
x.append("boolean ");
break;
}
x.append(varName);
while (isArray > 0) {
x.append("[]");
isArray--;
}
return (x.toString());
}
/**
* Returns the next signature from a string of concatenated signatures.
* For example if the signature was "[BII", this method would return
* "II"
*/
public static String nextSig(String sig) {
int ndx = 0;
String x;
while (sig.charAt(ndx) == "[")
ndx++;
if (sig.charAt(ndx) == "L") {
while (sig.charAt(ndx) != ";")
ndx++;
}
ndx++;
x = (sig.substring(ndx));
return (x);
}
/**
* Print the name of a class in "canonical form"
*/
private String printClassName(String s) {
StringBuffer x;
if (s.charAt(0) == "[") {
return(typeString(s, ""));
}
x = new StringBuffer();
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == "/")
x.append(".");
else
x.append(s.charAt(j));
}
return (x.toString());
}
public String getClassName() {
return printClassName(thisClass.arg1.strValue);
}
/**
* The boring version of display().
*/
public String toString() {
return("Class File (Version "+majorVersion+"."+minorVersion+
") for class "+thisClass.arg1);
}
/**
* Write out a text version of this class.
*/
public void display(PrintStream ps)
throws Exception {
int i;
String myClassName;
String mySuperClassName;
String packageName = null;
if (! isValidClass) {
ps.println("Not a valid class");
}
myClassName = printClassName(thisClass.arg1.strValue);
mySuperClassName = printClassName(superClass.arg1.strValue);
if (myClassName.indexOf(".") > 0) {
packageName =
myClassName.substring(0, myClassName.lastIndexOf("."));
myClassName = myClassName.substring(myClassName.lastIndexOf(".")+1);
ps.println("package "+packageName+"\n");
}
for (i = 1; i < constantPool.length; i++) {
if (constantPool[i] == null)
continue;
if ((constantPool[i] == thisClass) ||
(constantPool[i] == superClass))
continue;
if (constantPool[i].type == ConstantPoolInfo.CLASS) {
String s = constantPool[i].arg1.strValue;
if (s.charAt(0) == "[")
continue;
s = printClassName(constantPool[i].arg1.strValue);
if ((packageName != null) && (s.startsWith(packageName)))
continue;
ps.println("import "+printClassName(s)+";");
}
}
ps.println();
ps.println("/*");
DataInputStream dis;
ConstantPoolInfo cpi;
if (attributes != null) {
ps.println(" * This class has "+attributes.length+
" optional class attributes.");
ps.println(" * These attributes are: ");
for (i = 0; i < attributes.length; i++) {
String attrName = attributes[i].name.strValue;
dis = new DataInputStream(new ByteArrayInputStream(attributes[i].data));
ps.println(" * Attribute "+(i+1)+" is of type "+attributes[i].name);
if (attrName.rupareTo("SourceFile") == 0) {
cpi = null;
try {
cpi = constantPool[dis.readShort()];
} catch (IOException e) { }
ps.println(" * SourceFile : "+cpi);
} else {
ps.println(" * TYPE ("+attrName+")");
}
}
} else {
ps.println(" * This class has NO optional class attributes.");
}
ps.println(" */\n");
ps.print(accessString(accessFlags)+"class "+myClassName+" extends "+
mySuperClassName);
if (interfaces != null) {
ps.print(" implements ");
for (i = 0; i < interfaces.length - 1; i++) {
ps.print(interfaces[i].arg1.strValue+", ");
}
ps.print(interfaces[interfaces.length-1].arg1.strValue);
}
ps.println(" {\n");
if (fields != null) {
ps.println("/* Instance Variables */");
for (i = 0; i < fields.length; i++) {
ps.println(" "+fields[i].toString(constantPool)+";");
}
}
if (methods != null) {
ps.println("\n/* Methods */");
for (i = 0; i < methods.length; i++) {
ps.println(" "+methods[i].toString(myClassName));
}
}
ps.println("\n}");
}
public ConstantPoolInfo getConstantRef(short index) {
return (constantPool[index]);
}
/**
* Add a single constant pool item and return its index.
* If the item is already in the pool then the index of
* the <i>preexisting</i> item is returned. Thus you cannot
* assume that a pointer to your item will be useful.
*/
public short addConstantPoolItem(ConstantPoolInfo item)
throws Exception {
ConstantPoolInfo newConstantPool[];
ConstantPoolInfo cp;
cp = item.inPool(constantPool);
if (cp != null)
return ConstantPoolInfo.indexOf(cp, constantPool);
newConstantPool = new ConstantPoolInfo[constantPool.length+1];
for (int i = 1; i < constantPool.length; i++) {
newConstantPool[i] = constantPool[i];
}
newConstantPool[constantPool.length] = item;
constantPool = newConstantPool;
return ConstantPoolInfo.indexOf(item, constantPool);
}
/**
* Add some items to the constant pool. This is used to add new
* items to the constant pool. The items references in arg1 and
* arg2 are expected to be valid pointers (if necessary). Pruning
* is done to prevent adding redundant items to the list and to
* preserve string space.
*
* The algorithm is simple, first identify pool items containing
* constants in the list of items to be added that are already
* in the constant pool. If any are found to already exist, change
* the pointers in the non-constant items to point to the ones in
* the pool rather than the ones in the list. Next check to see
* if any of the non-constant items are already in the pool and
* if so fix up the others in the list to point to the ones in
* the pool. Finally, add any items (there must be at least one)
* from the item list that aren"t already in the pool, all of
* the pointers will already be fixed.
*
* NOTE: Since constants in the constant pool may be referenced
* <i>inside</i> the opaque portion of attributes the constant
* table cannot be re-ordered, only extended.
*/
public void addConstantPoolItems(ConstantPoolInfo items[]) {
ConstantPoolInfo newArg;
ConstantPoolInfo newConstantPool[];
boolean delete[] = new boolean[items.length];
/* Step one, look for matching constants */
for (int j = 0; j < items.length; j++) {
if ( (items[j].type == ConstantPoolInfo.ASCIZ) ||
(items[j].type == ConstantPoolInfo.UNICODE) ||
(items[j].type == ConstantPoolInfo.INTEGER) ||
(items[j].type == ConstantPoolInfo.LONG) ||
(items[j].type == ConstantPoolInfo.FLOAT) ||
(items[j].type == ConstantPoolInfo.DOUBLE)) {
// Look for this item in the constant pool
delete[j] = false;
newArg = items[j].inPool(constantPool);
if (newArg != null) {
// replace the references in our list.
delete[j] = true; // mark it for deletion
for (int i = 0; i < items.length; i++) {
if (items[i].arg1 == items[j])
items[i].arg1 = newArg;
if (items[i].arg2 == items[j])
items[i].arg2 = newArg;
}
}
}
}
/* Step two : now match everything else */
for (int j = 0; j < items.length; j++) {
if ( (items[j].type == ConstantPoolInfo.CLASS) ||
(items[j].type == ConstantPoolInfo.FIELDREF) ||
(items[j].type == ConstantPoolInfo.METHODREF) ||
(items[j].type == ConstantPoolInfo.STRING) ||
(items[j].type == ConstantPoolInfo.INTERFACE) ||
(items[j].type == ConstantPoolInfo.NAMEANDTYPE)) {
// Look for this item in the constant pool
delete[j] = false;
newArg = items[j].inPool(constantPool);
if (newArg != null) {
// replace the references in our list.
delete[j] = true; // mark it for deletion
for (int i = 0; i < items.length; i++) {
if (items[i].arg1 == items[j])
items[i].arg1 = newArg;
if (items[i].arg2 == items[j])
items[i].arg2 = newArg;
}
}
}
}
/* Step three: Add the surviving items to the pool */
int count = 0;
for (int i = 0; i < items.length; i++) {
if (! delete[i])
count++;
}
// count == # of survivors
newConstantPool = new ConstantPoolInfo[constantPool.length + count];
for (int i = 1; i < constantPool.length; i++) {
newConstantPool[i] = constantPool[i];
}
// newConstantPool == existing constantPool
int ndx = 0;
for (int i = constantPool.length; i < newConstantPool.length; i++) {
while (delete[ndx])
ndx++;
newConstantPool[i] = items[ndx];
ndx++;
}
// newConstantPool == existing + new
constantPool = newConstantPool;
// all done.
}
/**
* Add a new optional class Attribute.
*
* Items is an array of constant pool items that are first added
* to the constant pool. At a minimum items[0] must be an ASCIZ
* item with the name of the attribute. If the body of the attribute
* references constant pool items these should be in the item list
* as well.
*/
public void addAttribute(AttributeInfo newAttribute) {
if (attributes == null) {
attributes = new AttributeInfo[1];
attributes[0] = newAttribute;
} else {
AttributeInfo newAttrList[] = new AttributeInfo[1+attributes.length];
for (int i = 0; i < attributes.length; i++) {
newAttrList[i] = attributes[i];
}
newAttrList[attributes.length] = newAttribute;
attributes = newAttrList;
}
}
/**
* Return the attribute named "name" from the class file.
*/
public AttributeInfo getAttribute(String name) {
if (attributes == null)
return null;
for (int i = 0; i < attributes.length; i++) {
if (name.rupareTo(attributes[i].name.toString()) == 0)
return attributes[i];
}
return (null);
}
/**
* Return a constant pool item from this class. (note does fixup
* of indexes to facilitate extracting nested or linked items.
*/
public ConstantPoolInfo getConstantPoolItem(short index)
throws Exception {
ConstantPoolInfo cp;
if ((index <= 0) || (index > (constantPool.length - 1)))
return (null);
cp = constantPool[index];
if (cp.arg1 != null)
cp.index1 = ConstantPoolInfo.indexOf(cp.arg1, constantPool);
if (cp.arg2 != null)
cp.index2 = ConstantPoolInfo.indexOf(cp.arg2, constantPool);
return cp;
}
/* Examples of mysterious things you can do to a class file before
* writing it back out. These methods are not currently functional.
* (that would be too easy :-)
*/
/**
* Map occurences of class <i>oldClass</i> to occurrences of
* class <i>newClass</i>. This method is used to retarget
* accesses to one class, seamlessly to another.
*
* The format for the class name is slash (/) separated so
* the class <tt>util.ClassFile</tt> would be represented as
* <tt>util/ClassFile</tt>
*/
public void mapClass(String oldClass, String newClass) {
if (debug)
System.out.println("Mapping class name "+oldClass+" ==> "+
newClass+" for class "+thisClass.arg1);
for (int i = 0; i < constantPool.length; i++) {
if (constantPool[i].type == ConstantPoolInfo.CLASS) {
String cname = constantPool[i].arg1.strValue;
if (cname.rupareTo(oldClass) == 0) {
if (debug) {
System.out.println("REPLACING "+cname+" with "+newClass);
}
constantPool[i].arg1.strValue = newClass;
}
}
}
}
/**
* Map occurences of package <i>oldPackage</i> to package
* <i>newPackage</i>.
*
* The format for the package name is slash (/) separated so
* the package <tt>java.util</tt> would be represented as
* <tt>java/util</tt>
*/
public void mapPackage(String oldPackage, String newPackage) {
for (int i = 0; i < constantPool.length; i++) {
if (constantPool[i].type == ConstantPoolInfo.CLASS) {
String cname = constantPool[i].arg1.strValue;
if (cname.startsWith(oldPackage)) {
constantPool[i].arg1.strValue = newPackage +
cname.substring(cname.lastIndexOf("/"));
}
}
}
}
/**
* Delete a named method from this class. This method is used
* to excise specific methods from the loaded class. The actual
* method code remains, however the method signature is deleted
* from the constant pool. If this method is called by a class
* the exception IncompatibleClassChangeException is generated
* by the runtime.
*/
public void deleteMethod(String name, String signature) {
for (int i = 0; i < constantPool.length; i++) {
if (constantPool[i].type == ConstantPoolInfo.CLASS) {
}
}
}
}
/*
* @(#)ConstantPoolInfo.java 1.5 95/08/16 Chuck McManis
*
* Copyright (c) 1996 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
* MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
/**
* This class defines an entry in the constant pool for a Java class.
* The class file is primarily composed of ConstantPool entries and
* manipulation is done by modifying those entries.
*
* @version 1.5, 16 Aug 1995
* @author Chuck McManis
* @see ClassFile
*/
class ConstantPoolInfo{
int type; // type of this item
String name; // String for the type
ConstantPoolInfo arg1; // index to first argument
ConstantPoolInfo arg2; // index to second argument
short index1, index2;
String strValue; // ASCIZ String value
int intValue;
long longValue;
float floatValue;
double doubleValue;
public static final int CLASS = 7;
public static final int FIELDREF = 9;
public static final int METHODREF = 10;
public static final int STRING = 8;
public static final int INTEGER = 3;
public static final int FLOAT = 4;
public static final int LONG = 5;
public static final int DOUBLE = 6;
public static final int INTERFACE = 11;
public static final int NAMEANDTYPE = 12;
public static final int ASCIZ = 1;
public static final int UNICODE = 2;
/**
* Construct a new ConstantPoolInfo object that is of type ASCIZ
*/
public ConstantPoolInfo(String value) {
index1 = -1;
index2 = -1;
arg1 = null;
arg2 = null;
type = ASCIZ;
strValue = value;
}
/**
* Construct a new ConstantPoolInfo object that is of type INTEGER
*/
public ConstantPoolInfo(int value) {
index1 = -1;
index2 = -1;
arg1 = null;
arg2 = null;
type = INTEGER;
intValue = value;
}
/**
* Construct a new ConstantPoolInfo object that is of type FLOAT
*/
public ConstantPoolInfo(float value) {
index1 = -1;
index2 = -1;
arg1 = null;
arg2 = null;
type = FLOAT;
floatValue = value;
}
/**
* Construct a new ConstantPoolInfo object that is of type LONG
*/
public ConstantPoolInfo(long value) {
index1 = -1;
index2 = -1;
arg1 = null;
arg2 = null;
type = LONG;
longValue = value;
}
/**
* Construct a new ConstantPoolInfo object that is of type DOUBLE
*/
public ConstantPoolInfo(double value) {
index1 = -1;
index2 = -1;
arg1 = null;
arg2 = null;
type = DOUBLE;
doubleValue = value;
}
/**
* Generic constructor
*/
public ConstantPoolInfo() {
index1 = -1;
index2 = -1;
arg1 = null;
arg2 = null;
type = -1;
}
/**
* return the type of this constant pool item.
*/
public int isType() {
return (type);
}
public boolean read(DataInputStream dis)
throws IOException {
int len;
char c;
type = dis.readByte();
switch (type) {
case CLASS:
name = "Class";
index1 = dis.readShort();
index2 = -1;
break;
case FIELDREF:
name = "Field Reference";
index1 = dis.readShort();
index2 = dis.readShort();
break;
case METHODREF:
name = "Method Reference";
index1 = dis.readShort();
index2 = dis.readShort();
break;
case INTERFACE:
name = "Interface Method Reference";
index1 = dis.readShort();
index2 = dis.readShort();
break;
case NAMEANDTYPE:
name = "Name and Type";
index1 = dis.readShort();
index2 = dis.readShort();
break;
case STRING:
name = "String";
index1 = dis.readShort();
index2 = -1;
break;
case INTEGER:
name = "Integer";
intValue = dis.readInt();
break;
case FLOAT:
name = "Float";
floatValue = dis.readFloat();
break;
case LONG:
name = "Long";
longValue = dis.readLong();
break;
case DOUBLE:
name = "Double";
doubleValue = dis.readDouble();
break;
case ASCIZ:
case UNICODE:
if (type == ASCIZ)
name = "ASCIZ";
else
name = "UNICODE";
StringBuffer xxBuf = new StringBuffer();
len = dis.readShort();
while (len > 0) {
c = (char) (dis.readByte());
xxBuf.append(c);
len--;
}
strValue = xxBuf.toString();
break;
default:
System.out.println("Warning bad type.");
}
return (true);
}
public void write(DataOutputStream dos, ConstantPoolInfo pool[])
throws IOException, Exception {
dos.write(type);
switch (type) {
case CLASS:
case STRING:
dos.writeShort(indexOf(arg1, pool));
break;
case FIELDREF:
case METHODREF:
case INTERFACE:
case NAMEANDTYPE:
dos.writeShort(indexOf(arg1, pool));
dos.writeShort(indexOf(arg2, pool));
break;
case INTEGER:
dos.writeInt(intValue);
break;
case FLOAT:
dos.writeFloat(floatValue);
break;
case LONG:
dos.writeLong(longValue);
break;
case DOUBLE:
dos.writeDouble(doubleValue);
break;
case ASCIZ:
case UNICODE:
dos.writeShort(strValue.length());
dos.writeBytes(strValue);
break;
default:
throw new Exception("ConstantPoolInfo::write() - bad type.");
}
}
public String toString() {
StringBuffer s;
if (type == ASCIZ) {
return(strValue);
}
if (type == INTEGER) {
return("= "+intValue);
}
if (type == LONG) {
return("= "+longValue);
}
if (type == FLOAT) {
return("= "+floatValue);
}
if (type == DOUBLE) {
return("= "+doubleValue);
}
s = new StringBuffer();
s.append(name);
s.append(":");
if (arg1 != null)
s.append(arg1.toString());
else if (index1 != -1)
s.append("I1["+index1+"], ");
if (arg2 != null)
s.append(arg2.toString());
else if (index2 != -1)
s.append("I2["+index2+"], ");
return (s.toString());
}
public static short indexOf(ConstantPoolInfo item,
ConstantPoolInfo pool[])
throws Exception {
for (int i = 0; i < pool.length; i++) {
if (item == pool[i])
return (short) i;
}
throw new Exception("ConstantPoolInfo:: indexOf() - item not in pool.");
}
/**
* Returns true if these constant pool items are identical.
*/
public boolean isEqual(ConstantPoolInfo cp) {
if (cp == null)
return false;
if (cp.type != type)
return (false);
switch (cp.type) {
case CLASS:
case STRING:
return (arg1 == cp.arg1);
case FIELDREF:
case METHODREF:
case INTERFACE:
case NAMEANDTYPE:
return ((arg1 == cp.arg1) && (arg2 == cp.arg2));
case INTEGER:
return (cp.intValue == intValue);
case FLOAT:
return (cp.floatValue == floatValue);
case LONG:
return (cp.longValue == longValue);
case DOUBLE:
return (cp.doubleValue == doubleValue);
case ASCIZ:
case UNICODE:
return (cp.strValue.rupareTo(strValue) == 0);
}
return (false);
}
/**
* Returns the reference to the constant pool item that is
* already in pool, that matches this one.
*/
public ConstantPoolInfo inPool(ConstantPoolInfo pool[]) {
for (int i = 1; i < pool.length; i++) {
if (isEqual(pool[i]))
return (pool[i]);
}
return null;
}
}
/*
* @(#)MethodInfo.java 1.4 95/08/16 Chuck McManis
*
* Copyright (c) 1996 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
* MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
/**
* This class describes a Method as it is stored in the class file.
* The attribute associated with method is the code that actually implements
* the method. Since we don"t need to manipulate the byte codes directly
* we leave them as an opaque chunk in the attributes[] array. References
* in the code are all references into the constant table so when we are
* modifing a class to use a different object we needn"t get into the code
* level.
*
* @version 1.4, 16 Aug 1995
* @author Chuck McManis
* @see ClassFile
*/
class MethodInfo {
short accessFlags;
ConstantPoolInfo name;
ConstantPoolInfo signature;
AttributeInfo attributes[];
/**
* Read a method_info from the data stream.
*/
public boolean read(DataInputStream di, ConstantPoolInfo pool[])
throws IOException {
int count;
accessFlags = di.readShort();
name = pool[di.readShort()];
signature = pool[di.readShort()];
count = di.readShort();
if (count != 0) {
attributes = new AttributeInfo[count];
for (int i = 0; i < count; i++) {
attributes[i] = new AttributeInfo(); // "code"
if (! attributes[i].read(di, pool)) {
return (false);
}
}
}
return (true);
}
/**
* Write out a method_info, do constant table fixups on the write.
*/
public void write(DataOutputStream dos, ConstantPoolInfo pool[])
throws IOException, Exception {
dos.writeShort(accessFlags);
dos.writeShort(ConstantPoolInfo.indexOf(name, pool));
dos.writeShort(ConstantPoolInfo.indexOf(signature, pool));
if (attributes == null) {
dos.writeShort(0);
} else {
dos.writeShort(attributes.length);
for (int i = 0; i < attributes.length; i++)
attributes[i].write(dos, pool);
}
}
/**
* print out the method, much as you would see it in the source
* file. The string ClassName is substituted for <init> when
* printing.
*/
public String toString(String className) {
StringBuffer x = new StringBuffer();
boolean isArray = false;
String paramSig;
String returnSig;
int ndx = 0;
StringBuffer parameterList = new StringBuffer();
char initialParameter = "a";
StringBuffer varName = new StringBuffer();
String s = signature.strValue;
paramSig = s.substring(s.indexOf("(")+1, s.indexOf(")"));
returnSig = s.substring(s.indexOf(")")+1);
x.append(ClassFile.accessString(accessFlags));
/* catch constructors */
if ((className != null) && (name.toString().startsWith("<init>")))
parameterList.append(className);
else
parameterList.append(name.toString());
parameterList.append("(");
if ((paramSig.length() > 0) && paramSig.charAt(0) != "V") {
while (paramSig.length() > 0) {
varName.setLength(0);
varName.append(initialParameter);
initialParameter++;
parameterList.append(
ClassFile.typeString(paramSig, varName.toString()));
paramSig = ClassFile.nextSig(paramSig);
if (paramSig.length() > 0)
parameterList.append(", ");
}
}
parameterList.append(")");
x.append(ClassFile.typeString(returnSig, parameterList.toString()));
x.append(";");
return (x.toString());
}
/**
* Generic toString method, init method is unchanged.
*/
public String toString() {
return (toString((String)null));
}
}
/*
* @(#)AttributeInfo.java 1.4 95/08/16 Chuck McManis
*
* Copyright (c) 1996 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
* MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
/**
* This class defines the generic Attribute type for Java class files.
* It is a little bit smart in that for some Attributes it can display
* them intelligently if it also has access to the constant pool of the
* current class.
*
* @version 1.4, 16 Aug 1995
* @author Chuck McManis
* @see ClassFile
*/
class AttributeInfo {
ConstantPoolInfo name; // attribute name
byte data[]; // attribute"s contents
public AttributeInfo(ConstantPoolInfo newName, byte newData[]) {
name = name;
data = newData;
}
public AttributeInfo() {
}
public boolean read(DataInputStream di, ConstantPoolInfo pool[])
throws IOException {
int len;
name = pool[di.readShort()];
len = di.readInt();
data = new byte[len];
len = di.read(data);
if (len != data.length)
return (false);
return (true);
}
public void write(DataOutputStream dos, ConstantPoolInfo pool[])
throws IOException, Exception {
dos.writeShort(ConstantPoolInfo.indexOf(name, pool));
dos.writeInt(data.length);
dos.write(data, 0, data.length);
}
short indexFromBytes(byte a[]) {
return (short)(((a[0] << 8) & (0xff << 8)) |
((a[1] << 0) & (0xff << 0)));
}
public String toString(ConstantPoolInfo pool[]) {
StringBuffer x = new StringBuffer();
String type = name.toString();
ConstantPoolInfo item;
if (type.rupareTo("ConstantValue") == 0) {
item = pool[indexFromBytes(data)];
return (item.toString());
} else if (type.rupareTo("SourceFile") == 0) {
item = pool[indexFromBytes(data)];
return (item.toString());
} else {
x.append(type+"<"+data.length+" bytes>");
}
return (x.toString());
}
public String toBoolean(ConstantPoolInfo pool[]) {
ConstantPoolInfo item = pool[indexFromBytes(data)];
if (item.intValue == 0)
return ("= false");
return ("= true");
}
public String toString() {
return (name.toString()+" <"+data.length+" bytes>");
}
}
/*
* @(#)FieldInfo.java 1.3 95/08/16 Chuck McManis
*
* Copyright (c) 1996 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING,
* MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
/**
* This class defines a FieldInfo in the class file. Fields are used to
* describe instance variables in a class. The toString() method is
* augmented by a version that takes an array of ConstantPoolInfo
* objects (a constant pool). When a constant pool is available the
* toString() method generates a declaration for the field as it would
* appear in Java source.
*
* @version 1.3, 16 Aug 1995
* @author Chuck McManis
* @see ClassFile
*/
class FieldInfo {
short accessFlags;
ConstantPoolInfo name;
ConstantPoolInfo signature;
AttributeInfo attributes[];
public boolean read(DataInputStream di, ConstantPoolInfo pool[])
throws IOException {
int count;
accessFlags = di.readShort();
name = pool[di.readShort()];
signature = pool[di.readShort()];
count = di.readShort();
if (count != 0) {
attributes = new AttributeInfo[count];
for (int i = 0; i < count; i++) {
attributes[i] = new AttributeInfo();
if (! attributes[i].read(di, pool))
return (false);
}
}
return (true);
}
public void write(DataOutputStream dos, ConstantPoolInfo pool[])
throws IOException, Exception {
dos.writeShort(accessFlags);
dos.writeShort(ConstantPoolInfo.indexOf(name, pool));
dos.writeShort(ConstantPoolInfo.indexOf(signature, pool));
if (attributes == null) {
dos.writeShort(0);
} else {
dos.writeShort(attributes.length);
for (int i = 0; i < attributes.length; i++) {
attributes[i].write(dos, pool);
}
}
}
public String toString() {
StringBuffer x = new StringBuffer();
x.append(ClassFile.accessString(accessFlags));
x.append(ClassFile.typeString(signature.toString(), name.toString()));
if (attributes != null) {
x.append(" = "+attributes[0].toString());
}
return (x.toString());
}
public String toString(ConstantPoolInfo pool[]) {
StringBuffer x = new StringBuffer();
String mytype;
x.append(ClassFile.accessString(accessFlags));
mytype = ClassFile.typeString(signature.toString(), name.toString());
x.append(mytype);
if (attributes != null) {
if (mytype.startsWith("boolean")) {
x.append(" "+attributes[0].toBoolean(pool));
} else
x.append(" "+attributes[0].toString(pool));
}
return (x.toString());
}
}
Object Reflection: create new instance
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 1995-1998 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies. Please refer to the file "copyright.html"
* for further important copyright and licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
import java.awt.Rectangle;
public class SampleNoArg {
public static void main(String[] args) {
Rectangle r = (Rectangle) createObject("java.awt.Rectangle");
System.out.println(r.toString());
}
static Object createObject(String className) {
Object object = null;
try {
Class classDefinition = Class.forName(className);
object = classDefinition.newInstance();
} catch (InstantiationException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (ClassNotFoundException e) {
System.out.println(e);
}
return object;
}
}
Provides a set of static methods that extend the Java metaobject
/*
Java Reflection in Action
Ira R. Forman and Nate Forman
ISBN 1932394184
Publisher: Manning Publications Co.
*/
/* Copyright 2002 -- Ira R. Forman and Nate Forman */
/**
* This class provides a set of static methods that extend the Java metaobject
* protocol.
*
* @author: Ira R. Forman
*/
import java.lang.reflect.*;
import java.util.*;
abstract public class Mopex {
/**
* Returns a syntactically correct name for a class object. If the class
* object represents an array, the proper number of square bracket pairs are
* appended to the component type.
*
* @return java.lang.String
* @param cls
* java.lang.Class
*/
//start extract classNameToString
public static String getTypeName(Class cls) {
if (!cls.isArray()) {
return cls.getName();
} else {
return getTypeName(cls.getComponentType()) + "[]";
}
}
//stop extract classNameToString
/**
* Returns an array of the superclasses of cls.
*
* @return java.lang.Class[]
* @param cls
* java.lang.Class
*/
//start extract getSuperclasses
public static Class[] getSuperclasses(Class cls) {
int i = 0;
for (Class x = cls.getSuperclass(); x != null; x = x.getSuperclass())
i++;
Class[] result = new Class[i];
i = 0;
for (Class x = cls.getSuperclass(); x != null; x = x.getSuperclass())
result[i++] = x;
return result;
}
//stop extract getSuperclasses
/**
* Returns an array of the instance variablies of the the specified class.
* An instance variable is defined to be a non-static field that is declared
* by the class or inherited.
*
* @return java.lang.Field[]
* @param cls
* java.lang.Class
*/
//start extract getInstanceVariables
public static Field[] getInstanceVariables(Class cls) {
List accum = new LinkedList();
while (cls != null) {
Field[] fields = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (!Modifier.isStatic(fields[i].getModifiers())) {
accum.add(fields[i]);
}
}
cls = cls.getSuperclass();
}
Field[] retvalue = new Field[accum.size()];
return (Field[]) accum.toArray(retvalue);
}
//stop extract getInstanceVariables
/**
* Returns an array of fields that are the declared instance variables of
* cls. An instance variable is a field that is not static.
*
* @return java.lang.reflect.Field[]
* @param cls
* java.lang.Class
*/
//start extract getDeclaredIVS
public static Field[] getDeclaredIVs(Class cls) {
Field[] fields = cls.getDeclaredFields();
// Count the IVs
int numberOfIVs = 0;
for (int i = 0; i < fields.length; i++) {
if (!Modifier.isStatic(fields[i].getModifiers()))
numberOfIVs++;
}
Field[] declaredIVs = new Field[numberOfIVs];
// Populate declaredIVs
int j = 0;
for (int i = 0; i < fields.length; i++) {
if (!Modifier.isStatic(fields[i].getModifiers()))
declaredIVs[j++] = fields[i];
}
return declaredIVs;
}
//stop extract getDeclaredIVS
/**
* Return an array of the supported instance variables of this class. A
* supported instance variable is not static and is either declared or
* inherited from a superclass.
*
* @return java.lang.reflect.Field[]
* @param cls
* java.lang.Class
*/
//start extract getSupportedIVS
public static Field[] getSupportedIVs(Class cls) {
if (cls == null) {
return new Field[0];
} else {
Field[] inheritedIVs = getSupportedIVs(cls.getSuperclass());
Field[] declaredIVs = getDeclaredIVs(cls);
Field[] supportedIVs = new Field[declaredIVs.length
+ inheritedIVs.length];
for (int i = 0; i < declaredIVs.length; i++) {
supportedIVs[i] = declaredIVs[i];
}
for (int i = 0; i < inheritedIVs.length; i++) {
supportedIVs[i + declaredIVs.length] = inheritedIVs[i];
}
return supportedIVs;
}
}
//stop extract getSupportedIVS
/**
* Returns an array of the methods that are not static.
*
* @return java.lang.reflect.Method[]
* @param cls
* java.lang.Class
*/
//start extract getInstanceMethods
public static Method[] getInstanceMethods(Class cls) {
List instanceMethods = new ArrayList();
for (Class c = cls; c != null; c = c.getSuperclass()) {
Method[] methods = c.getDeclaredMethods();
for (int i = 0; i < methods.length; i++)
if (!Modifier.isStatic(methods[i].getModifiers()))
instanceMethods.add(methods[i]);
}
Method[] ims = new Method[instanceMethods.size()];
for (int j = 0; j < instanceMethods.size(); j++)
ims[j] = (Method) instanceMethods.get(j);
return ims;
}
//stop extract getInstanceMethods
/**
* Returns an array of methods to which instances of this class respond.
*
* @return java.lang.reflect.Method[]
* @param cls
* java.lang.Class
*/
//start extract getSupportedMethods
public static Method[] getSupportedMethods(Class cls) {
return getSupportedMethods(cls, null);
}
//stop extract getSupportedMethods
/**
* This method retrieves the modifiers of a Method without the unwanted
* modifiers specified in the second parameter. Because this method uses
* bitwise operations, multiple unwanted modifiers may be specified by
* bitwise or.
*
* @return int
* @param m
* java.lang.Method
* @param unwantedModifiers
* int
*/
//start extract getModifiersWithout
public static int getModifiersWithout(Method m, int unwantedModifiers) {
int mods = m.getModifiers();
return (mods ^ unwantedModifiers) & mods;
}
//stop extract getModifiersWithout
/**
* Returns a Method that has the signature specified by the calling
* parameters.
*
* @return Method
* @param cls
* java.lang.Class
* @param name
* String
* @param paramTypes
* java.lang.Class[]
*/
//start extract getSupportedMethod
public static Method getSupportedMethod(Class cls, String name,
Class[] paramTypes) throws NoSuchMethodException {
if (cls == null) {
throw new NoSuchMethodException();
}
try {
return cls.getDeclaredMethod(name, paramTypes);
} catch (NoSuchMethodException ex) {
return getSupportedMethod(cls.getSuperclass(), name, paramTypes);
}
}
//stop extract getSupportedMethod
/**
* Returns a Method array of the methods to which instances of the specified
* respond except for those methods defined in the class specifed by limit
* or any of its superclasses. Note that limit is usually used to eliminate
* them methods defined by java.lang.Object.
*
* @return Method[]
* @param cls
* java.lang.Class
* @param limit
* java.lang.Class
*/
//start extract getSupportedMethods
public static Method[] getSupportedMethods(Class cls, Class limit) {
Vector supportedMethods = new Vector();
for (Class c = cls; c != limit; c = c.getSuperclass()) {
Method[] methods = c.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
boolean found = false;
for (int j = 0; j < supportedMethods.size(); j++)
if (equalSignatures(methods[i], (Method) supportedMethods
.elementAt(j))) {
found = true;
break;
}
if (!found)
supportedMethods.add(methods[i]);
}
}
Method[] mArray = new Method[supportedMethods.size()];
for (int k = 0; k < mArray.length; k++)
mArray[k] = (Method) supportedMethods.elementAt(k);
return mArray;
}
//stop extract getSupportedMethods
/**
* This field is initialized with a method object for the equalSignatures
* method. This is an optimization in that selectMethods can use this field
* instead of calling getMethod each time it is called.
*/
//start extract equalSignaturesMethod
static private Method equalSignaturesMethod;
static {
Class[] fpl = { Method.class, Method.class };
try {
equalSignaturesMethod = Mopex.class.getMethod("equalSignatures",
fpl);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
//stop extract equalSignaturesMethod
/**
* Determines if the signatures of two method objects are equal. In Java, a
* signature comprises the method name and the array of of formal parameter
* types. For two signatures to be equal, the method names must be the same
* and the formal parameters must be of the same type (in the same order).
*
* @return boolean
* @param m1
* java.lang.Method
* @param m2
* java.lang.Method
*/
//start extract equalSignatures
public static boolean equalSignatures(Method m1, Method m2) {
if (!m1.getName().equals(m2.getName()))
return false;
if (!Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes()))
return false;
return true;
}
//stop extract equalSignatures
/**
* Return a string that represents the signature of the specified method.
*
* @return String
* @param m
* java.lang.Method
*/
//start extract signatureToString
public static String signatureToString(Method m) {
return m.getName() + "("
+ formalParametersToString(m.getParameterTypes()) + ")";
}
//stop extract signatureToString
/**
* Returns a string that can be used as a formal parameter list for a method
* that has the parameter types of the specified array.
*
* @return String
* @param pts
* java.lang.Class[]
*/
//start extract formalParametersToString
public static String formalParametersToString(Class[] pts) {
String result = "";
for (int i = 0; i < pts.length; i++) {
result += getTypeName(pts[i]) + " p" + i;
if (i < pts.length - 1)
result += ",";
}
return result;
}
//stop extract formalParametersToString
/**
* Returns a string that is an actual parameter list that matches the formal
* parameter list produced by formalParametersToString.
*
* @return String
* @param pts
* java.lang.Class[]
*/
//start extract actualParametersToString
public static String actualParametersToString(Class[] pts) {
String result = "";
for (int i = 0; i < pts.length; i++) {
result += "p" + i;
if (i < pts.length - 1)
result += ",";
}
return result;
}
//stop extract actualParametersToString
/**
* Returns a String that represents the header for a constructor.
*
* @return String
* @param c
* java.lang.Constructor
*/
//start extract constructorHeaderToString
public static String headerToString(Constructor c) {
String mods = Modifier.toString(c.getModifiers());
if (mods.length() == 0)
return headerSuffixToString(c);
else
return mods + " " + headerSuffixToString(c);
}
//stop extract constructorHeaderToString
/**
* Returns a String that represents the header suffix for a constructor. The
* term "header suffix" is not a standard Java term. We use it to mean the
* Java header without the modifiers.
*
* @return String
* @param c
* java.lang.Constructor
*/
//start extract constructorHeaderToString
public static String headerSuffixToString(Constructor c) {
String header = signatureToString(c);
Class[] eTypes = c.getExceptionTypes();
if (eTypes.length != 0)
header += " throws " + classArrayToString(eTypes);
return header;
}
//stop extract constructorHeaderToString
/**
* Returns a String that represents the signature for a constructor.
*
* @return String
* @param c
* java.lang.Constructor
*/
//start extract constructorHeaderToString
public static String signatureToString(Constructor c) {
return c.getName() + "("
+ formalParametersToString(c.getParameterTypes()) + ")";
}
//stop extract constructorHeaderToString
/**
* Returns a String that represents the header of a method.
*
* @return String
* @param m
* java.lang.Method
*/
//start extract headerToString
public static String headerToString(Method m) {
String mods = Modifier.toString(m.getModifiers());
if (mods.length() == 0)
return headerSuffixToString(m);
else
return mods + " " + headerSuffixToString(m);
}
//stop extract headerToString
/**
* Returns a String that represents the suffix of the header of a method.
* The suffix of a header is not a standard Java term. We use the term to
* mean the Java header without the method modifiers.
*
* @return String
* @param m
* java.lang.Method
*/
//start extract headerToString
public static String headerSuffixToString(Method m) {
String header = getTypeName(m.getReturnType()) + " "
+ signatureToString(m);
Class[] eTypes = m.getExceptionTypes();
if (eTypes.length != 0) {
header += " throws " + classArrayToString(eTypes);
}
return header;
}
//stop extract headerToString
/**
* Returns a String that is a comma separated list of the typenames of the
* classes in the array pts.
*
* @return String
* @param pts
* java.lang.Class[]
*/
//start extract classArrayToString
public static String classArrayToString(Class[] pts) {
String result = "";
for (int i = 0; i < pts.length; i++) {
result += getTypeName(pts[i]);
if (i < pts.length - 1)
result += ",";
}
return result;
}
//stop extract classArrayToString
/**
* Turns true if and only if the header suffixes of the two specified
* methods are equal. The header suffix is defined to be the signature, the
* return type, and the exception types.
*
* @return boolean
* @param m1
* java.lang.Method
* @param m2
* java.lang.Method
*/
public static boolean equalsHeaderSuffixes(Method m1, Method m2) {
if (m1.getReturnType() != m2.getReturnType())
return false;
if (!Arrays.equals(m1.getExceptionTypes(), m2.getExceptionTypes()))
return false;
return equalSignatures(m1, m2);
}
/**
* Creates constructor with the signature of c and a new name. It adds some
* code after generating a super statement to call c. This method is used
* when generating a subclass of class that declared c.
*
* @return String
* @param c
* java.lang.Constructor
* @param name
* String
* @param code
* String
*/
//start extract createRenamedConstructor
public static String createRenamedConstructor(Constructor c, String name,
String code) {
Class[] pta = c.getParameterTypes();
String fpl = formalParametersToString(pta);
String apl = actualParametersToString(pta);
Class[] eTypes = c.getExceptionTypes();
String result = name + "(" + fpl + ")\n";
if (eTypes.length != 0)
result += " throws " + classArrayToString(eTypes) + "\n";
result += "{\n super(" + apl + ");\n" + code + "}\n";
return result;
}
//stop extract createRenamedConstructor
/**
* Returns a String that is formatted as a Java method declaration having
* the same header as the specified method but with the code parameter
* substituted for the method body.
*
* @return String
* @param m
* java.lang.Method
* @param code
* String
*/
//start extract createReplacementMethod
public static String createReplacementMethod(Method m, String code) {
Class[] pta = m.getParameterTypes();
String fpl = formalParametersToString(pta);
Class[] eTypes = m.getExceptionTypes();
String result = m.getName() + "(" + fpl + ")\n";
if (eTypes.length != 0)
result += " throws " + classArrayToString(eTypes) + "\n";
result += "{\n" + code + "}\n";
return result;
}
//stop extract createReplacementMethod
/**
* Returns a string for a cooperative override of the method m. That is, The
* string has the same return type and signature as m but the body has a
* super call that is sandwiched between the strings code1 and code2.
*
* @return String
* @param m
* java.lang.Method
* @param code1
* String
* @param code2
* String
*/
//start extract createCooperativeWrapper
public static String createCooperativeWrapper(Method m, String code1,
String code2) {
Class[] pta = m.getParameterTypes();
Class retType = m.getReturnType();
String fpl = formalParametersToString(pta);
String apl = actualParametersToString(pta);
Class[] eTypes = m.getExceptionTypes();
String result = retType.getName() + " " + m.getName() + "(" + fpl
+ ")\n";
if (eTypes.length != 0)
result += " throws " + classArrayToString(eTypes) + "\n";
result += "{\n" + code1 + " ";
if (retType != void.class)
result += retType.getName() + " cooperativeReturnValue = ";
result += "super." + m.getName() + "(" + apl + ");\n";
result += code2;
if (retType != void.class)
result += " return cooperativeReturnValue;\n";
result += "}\n";
return result;
}
/**
* Returns the method object for the unique method named mName. If no such
* method exists, a null is returned. If there is more than one such method,
* a runtime exception is thrown.
*
* @return Method
* @param cls
* java.lang.Class
* @param mName
* String
*/
public static Method getUniquelyNamedMethod(Class cls, String mName) {
Method result = null;
Method[] mArray = cls.getDeclaredMethods();
for (int i = 0; i < mArray.length; i++)
if (mName.equals(mArray[i].getName())) {
if (result == null)
result = mArray[i];
else
throw new RuntimeException("name is not unique");
}
return result;
}
/**
* Finds the first (from the bottom of the inheritance hierarchy) field with
* the specified name. Note that Class.getField returns only public fields.
*
* @return Field
* @param cls
* java.lang.Class
* @param name
* String
*/
//start extract findField
public static Field findField(Class cls, String name)
throws NoSuchFieldException {
if (cls != null) {
try {
return cls.getDeclaredField(name);
} catch (NoSuchFieldException e) {
return findField(cls.getSuperclass(), name);
}
} else {
throw new NoSuchFieldException();
}
}
}
Reflect1 shows the information about the class named in argv
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.lang.reflect.*;
/**
* Reflect1 shows the information about the class named in argv[0].
* "Reflectance" is used to look up that information.
*/
public class Reflect1 {
public static void main(String[] args)
{
new Reflect1().run(new String[]{"javax.swing.JComponent","java.util.ArrayList"});
}
public void run(String classes[]) {
for (int i=0; i<classes.length; i++)
try {
Class c = Class.forName(classes[i]);
Method methods[] = c.getMethods();
for (int m = 0; m < methods.length; m++)
System.out.println(methods[m].toString());
} catch (ClassNotFoundException e) {
System.err.println("Error: Class " +
classes[i] + " not found!");
} catch (Exception e) {
System.err.println(e);
}
}
}
Return a String representation of an object"s overall identity
import java.lang.reflect.Array;
import java.util.Arrays;
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//Revised from springframework
/**
* Miscellaneous object utility methods. Mainly for internal use within the
* framework; consider Jakarta"s Commons Lang for a more comprehensive suite
* of object utilities.
*
* @author Juergen Hoeller
* @author Keith Donald
* @author Rod Johnson
* @author Rob Harrop
* @author Alex Ruiz
* @since 19.03.2004
* @see org.apache.rumons.lang.ObjectUtils
*/
abstract class ObjectUtils {
private static final int INITIAL_HASH = 7;
private static final int MULTIPLIER = 31;
private static final String EMPTY_STRING = "";
private static final String NULL_STRING = "null";
private static final String ARRAY_START = "{";
private static final String ARRAY_END = "}";
private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
/**
* Return a String representation of an object"s overall identity.
* @param obj the object (may be <code>null</code>)
* @return the object"s identity as String representation,
* or an empty String if the object was <code>null</code>
*/
public static String identityToString(Object obj) {
if (obj == null) {
return EMPTY_STRING;
}
return obj.getClass().getName() + "@" + getIdentityHexString(obj);
}
/**
* Return a hex String form of an object"s identity hash code.
* @param obj the object
* @return the object"s identity code in hex notation
*/
public static String getIdentityHexString(Object obj) {
return Integer.toHexString(System.identityHashCode(obj));
}
}
Show a couple of things you can do with a Class object
import java.lang.reflect.Method;
import java.util.Date;
/**
* Show a couple of things you can do with a Class object.
*
* @author Ian F. Darwin, ian darwinsys.ru
* @version $Id: Simple.java,v 1.1 2002/10/26 14:34:28 ian Exp $
*/
public class Simple {
public static void main(String[] argv) throws Exception {
Class c = Class.forName("java.util.Date");
Date d = (Date) c.newInstance();
System.out.println("Today is " + d);
System.out.println("d is of class " + c.getName());
Method[] methods = c.getMethods();
// Just print the first few to avoid filling the screen.
for (int i = 0; i < 10; i++)
System.out.println(methods[i].toString());
}
}
Show that you can, in fact, take the class of a primitive
import java.lang.reflect.Method;
/**
* Show that you can, in fact, take the .class of a primitive.
*/
public class PrimsDotClass {
public static void main(String[] args) {
Class c = int.class;
System.out.println(c.getName());
Method[] methods = c.getMethods();
System.out.println(c.getName() + " has " + methods.length + " methods");
}
}
Show the class keyword and getClass() method in action
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.util.Calendar;
/**
* Show the class keyword and getClass() method in action. The class keyword can
* be applied to any type known at compile time.
*
* @author Ian F. Darwin, http://www.darwinsys.ru/
* @version $Id: ClassKeyword.java,v 1.4 2004/02/09 03:33:51 ian Exp $
*/
public class ClassKeyword {
public static void main(String[] argv) {
//+
System.out.println("Trying the ClassName.class keyword:");
System.out.println("Object class: " + Object.class);
System.out.println("String class: " + String.class);
System.out.println("String[] class: " + String[].class);
System.out.println("Calendar class: " + Calendar.class);
System.out.println("Current class: " + ClassKeyword.class);
System.out.println("Class for int: " + int.class);
System.out.println();
System.out.println("Trying the instance.getClass() method:");
System.out.println("Sir Robin the Brave".getClass());
System.out.println(Calendar.getInstance().getClass());
//-
}
}
Simple Demonstration of a ClassLoader WILL NOT COMPILE OUT OF THE BOX
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Hashtable;
/**
* Simple Demonstration of a ClassLoader WILL NOT COMPILE OUT OF THE BOX -- WILL
* ONLY WORK AS PART OF THE CLASSLOADER EXERCISE. See ClassLoader1 for a working
* version.
*/
public class ClassLoaderDemo0 extends ClassLoader {
/** The Hashtable to keep track of classes, to avoid re-loading them */
protected Hashtable cache = new Hashtable();
/** INSERT HERE THE RESULT OF DUMPING DEMO.CLASS */
byte[] data /* = ... */;
int dataLength;
/** END OF INSERTION OF THE RESULT OF DUMPING DEMO.CLASS */
/** "load", that is, generate, the data for the class */
private byte[] genClassData(String name) {
if (dataLength != data.length) // EXPECT COMPILE ERROR in javasrc
throw new IllegalArgumentException("data corrupt, " + dataLength
+ "!=" + data.length);
byte[] bd = new byte[data.length];
for (int i = 0; i < bd.length; i++)
bd[i] = (byte) data[i];
return bd;
}
public synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class c = (Class) cache.get(name);
if (c == null) {
// System.out.println("loadClass: About to genClassData " + name);
byte mydata[] = genClassData(name);
// System.out.println("loadClass: About to defineClass " + name);
c = defineClass(name, mydata, 0, mydata.length);
System.out.println("loadClass: storing " + name + " in cache.");
cache.put(name, c);
} else
System.out.println("loadClass: found " + name + " in cache.");
if (resolve) {
System.out.println("loadClass: About to resolveClass " + name);
resolveClass(c);
}
return c;
}
public static void main(String[] argv) {
System.out.println("ClassLoaderDemo starting");
ClassLoaderDemo0 loader = new ClassLoaderDemo0();
Class c = null;
Object demo;
try {
/* Load the "Demo" class from memory */
System.out.println("About to load class Demo");
c = loader.loadClass("Demo", true);
System.out.println("About to instantiate class Demo");
demo = c.newInstance();
System.out.println("Got Demo class loaded: " + demo);
/* Now try to call a method */
Method mi = c.getMethod("test", null);
mi.invoke(demo, null);
} catch (InvocationTargetException e) {
// The invoked method threw an exception. We get it
// wrapped up inside another exception, hence the
// extra call here:
e.getTargetException().printStackTrace();
System.out.println("Could not run test method");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Could not run test method");
}
}
}
This class shows using Reflection to get a field from another class
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.lang.reflect.Field;
import java.util.Calendar;
/** This class shows using Reflection to get a field from another class. */
public class FindField {
public static void main(String[] unused) throws NoSuchFieldException,
IllegalAccessException {
// Create instance of FindField
FindField gf = new FindField();
// Create instance of target class (YearHolder defined below).
Object o = new YearHolder();
// Use gf to extract a field from o.
System.out.println("The value of "currentYear" is: "
+ gf.intFieldValue(o, "currentYear"));
}
int intFieldValue(Object o, String name) throws NoSuchFieldException,
IllegalAccessException {
Class c = o.getClass();
Field fld = c.getField(name);
int value = fld.getInt(o);
return value;
}
}
/** This is just a class that we want to get a field from */
class YearHolder {
/** Just a field that is used to show getting a field"s value. */
public int currentYear = Calendar.getInstance().get(Calendar.YEAR);
}
Use reflection to dynamically discover the capabilities of a class.
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Main {
public static void main(String args[]) throws Exception {
Class c = Class.forName("MyClass");
Constructor constructors[] = c.getDeclaredConstructors();
Object obj = null;
for (Constructor cons : constructors) {
Class[] params = cons.getParameterTypes();
if (params.length == 1 && params[0] == int.class) {
obj = cons.newInstance(10);
break;
}
}
if (obj == null) {
System.out.println("Can"t Create MyClass object.");
return;
}
}
}
class MyClass {
private int count;
MyClass(int c) {
System.out.println("MyClass(int):" + c);
count = c;
}
MyClass() {
System.out.println("MyClass()");
count = 0;
}
void setCount(int c) {
System.out.println("setCount(int): " + c);
count = c;
}
int getCount() {
System.out.println("getCount():" + count);
return count;
}
void showcount() {
System.out.println("count is " + count);
}
}
Use reflection to get console char set
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import static java.lang.System.out;
import java.io.Console;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.Charset;
public class ConsoleCharset {
public static void main(String... args) {
Constructor[] ctors = Console.class.getDeclaredConstructors();
Constructor ctor = null;
for (int i = 0; i < ctors.length; i++) {
ctor = ctors[i];
if (ctor.getGenericParameterTypes().length == 0)
break;
}
try {
ctor.setAccessible(true);
Console c = (Console) ctor.newInstance();
Field f = c.getClass().getDeclaredField("cs");
f.setAccessible(true);
out.format("Console charset : %s%n", f.get(c));
out.format("Charset.defaultCharset(): %s%n", Charset.defaultCharset());
// production code should handle these exceptions more gracefully
} catch (InstantiationException x) {
x.printStackTrace();
} catch (InvocationTargetException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
} catch (NoSuchFieldException x) {
x.printStackTrace();
}
}
}