6572945: javah should be written as an annotation processor, not a doclet

Reviewed-by: darcy
This commit is contained in:
Jonathan Gibbons 2009-09-23 19:15:04 -07:00
parent 6e3d970196
commit e116c27b51
36 changed files with 6639 additions and 1038 deletions

View file

@ -286,10 +286,10 @@
jarclasspath="javadoc.jar doclets.jar javac.jar"/>
</target>
<target name="build-javah" depends="build-javadoc">
<target name="build-javah" depends="build-javac">
<build-tool name="javah"
includes="${javah.includes}"
jarclasspath="javadoc.jar doclets.jar javac.jar"/>
jarclasspath="javac.jar"/>
</target>
<target name="build-classes-javah" depends="build-classes-javadoc">

View file

@ -27,15 +27,32 @@ package com.sun.tools.javah;
import java.io.UnsupportedEncodingException;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import com.sun.javadoc.*;
import java.io.*;
import java.util.Stack;
import java.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
/**
* An abstraction for generating support files required by native methods.
@ -43,31 +60,39 @@ import java.util.Arrays;
* original writing, this interface is rich enough to support JNI and the
* old 1.0-style native method interface.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Sucheta Dambalkar(Revised)
*/
public abstract class Gen {
protected String lineSep = System.getProperty("line.separator");
RootDoc root;
protected ProcessingEnvironment processingEnvironment;
protected Types types;
protected Elements elems;
protected Mangle mangler;
protected Util util;
protected Gen(Util util) {
this.util = util;
}
/*
* List of classes for which we must generate output.
*/
protected ClassDoc[] classes;
protected Set<TypeElement> classes;
static private final boolean isWindows =
System.getProperty("os.name").startsWith("Windows");
public Gen(RootDoc root){
this.root = root;
}
/**
* Override this abstract method, generating content for the named
* class into the outputstream.
*/
protected abstract void write(OutputStream o, ClassDoc clazz)
throws ClassNotFoundException;
protected abstract void write(OutputStream o, TypeElement clazz) throws Util.Exit;
/**
* Override this method to provide a list of #include statements
@ -78,31 +103,29 @@ public abstract class Gen {
/*
* Output location.
*/
protected String outDir;
protected String outFile;
protected JavaFileManager fileManager;
protected JavaFileObject outFile;
public void setOutDir(String outDir) {
/* Check important, otherwise concatenation of two null strings
* produces the "nullnull" String.
*/
if (outDir != null) {
this.outDir = outDir + System.getProperty("file.separator");
File d = new File(outDir);
if (!d.exists())
if (!d.mkdirs())
Util.error("cant.create.dir", d.toString());
}
public void setFileManager(JavaFileManager fm) {
fileManager = fm;
}
public void setOutFile(String outFile) {
public void setOutFile(JavaFileObject outFile) {
this.outFile = outFile;
}
public void setClasses(ClassDoc[] classes) {
public void setClasses(Set<TypeElement> classes) {
this.classes = classes;
}
void setProcessingEnvironment(ProcessingEnvironment pEnv) {
processingEnvironment = pEnv;
elems = pEnv.getElementUtils();
types = pEnv.getTypeUtils();
mangler = new Mangle(elems, types);
}
/*
* Smartness with generated files.
*/
@ -116,12 +139,11 @@ public abstract class Gen {
* We explicitly need to write ASCII files because that is what C
* compilers understand.
*/
protected PrintWriter wrapWriter(OutputStream o) {
protected PrintWriter wrapWriter(OutputStream o) throws Util.Exit {
try {
return new
PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
return new PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
} catch (UnsupportedEncodingException use) {
Util.bug("encoding.iso8859_1.not.found");
util.bug("encoding.iso8859_1.not.found");
return null; /* dead code */
}
}
@ -133,26 +155,25 @@ public abstract class Gen {
* Buffer size chosen as an approximation from a single sampling of:
* expr `du -sk` / `ls *.h | wc -l`
*/
public void run() throws IOException, ClassNotFoundException {
public void run() throws IOException, ClassNotFoundException, Util.Exit {
int i = 0;
if (outFile != null) {
/* Everything goes to one big file... */
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
writeFileTop(bout); /* only once */
for (i = 0; i < classes.length; i++) {
write(bout, classes[i]);
for (TypeElement t: classes) {
write(bout, t);
}
writeIfChanged(bout.toByteArray(), outFile);
} else {
/* Each class goes to its own file... */
for (i = 0; i < classes.length; i++) {
for (TypeElement t: classes) {
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
writeFileTop(bout);
ClassDoc clazz = classes[i];
write(bout, clazz);
writeIfChanged(bout.toByteArray(), getFileName(clazz.qualifiedName()));
write(bout, t);
writeIfChanged(bout.toByteArray(), getFileObject(t.getQualifiedName()));
}
}
}
@ -162,8 +183,7 @@ public abstract class Gen {
* is done if either the file doesn't exist or if the contents are
* different.
*/
private void writeIfChanged(byte[] b, String file) throws IOException {
File f = new File(file);
private void writeIfChanged(byte[] b, FileObject file) throws IOException {
boolean mustWrite = false;
String event = "[No need to update file ";
@ -171,71 +191,80 @@ public abstract class Gen {
mustWrite = true;
event = "[Forcefully writing file ";
} else {
if (!f.exists()) {
InputStream in;
byte[] a;
try {
// regrettably, there's no API to get the length in bytes
// for a FileObject, so we can't short-circuit reading the
// file here
in = file.openInputStream();
a = readBytes(in);
if (!Arrays.equals(a, b)) {
mustWrite = true;
event = "[Overwriting file ";
}
} catch (FileNotFoundException e) {
mustWrite = true;
event = "[Creating file ";
} else {
int l = (int)f.length();
if (b.length != l) {
mustWrite = true;
event = "[Overwriting file ";
} else {
/* Lengths are equal, so read it. */
byte[] a = new byte[l];
FileInputStream in = new FileInputStream(f);
if (in.read(a) != l) {
in.close();
/* This can't happen, we already checked the length. */
Util.error("not.enough.bytes", Integer.toString(l),
f.toString());
}
in.close();
while (--l >= 0) {
if (a[l] != b[l]) {
mustWrite = true;
event = "[Overwriting file ";
}
}
}
}
}
if (Util.verbose)
Util.log(event + file + "]");
if (util.verbose)
util.log(event + file + "]");
if (mustWrite) {
OutputStream out = new FileOutputStream(file);
OutputStream out = file.openOutputStream();
out.write(b); /* No buffering, just one big write! */
out.close();
}
}
protected String defineForStatic(ClassDoc c, FieldDoc f){
protected byte[] readBytes(InputStream in) throws IOException {
try {
byte[] array = new byte[in.available() + 1];
int offset = 0;
int n;
while ((n = in.read(array, offset, array.length - offset)) != -1) {
offset += n;
if (offset == array.length)
array = Arrays.copyOf(array, array.length * 2);
}
String cnamedoc = c.qualifiedName();
String fnamedoc = f.name();
return Arrays.copyOf(array, offset);
} finally {
in.close();
}
}
String cname = Mangle.mangle(cnamedoc, Mangle.Type.CLASS);
String fname = Mangle.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
protected String defineForStatic(TypeElement c, VariableElement f)
throws Util.Exit {
CharSequence cnamedoc = c.getQualifiedName();
CharSequence fnamedoc = f.getSimpleName();
if (!f.isStatic())
Util.bug("tried.to.define.non.static");
String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
if (f.isFinal()) {
if (!f.getModifiers().contains(Modifier.STATIC))
util.bug("tried.to.define.non.static");
if (f.getModifiers().contains(Modifier.FINAL)) {
Object value = null;
value = f.constantValue();
value = f.getConstantValue();
if (value != null) { /* so it is a ConstantExpression */
String constString = null;
if ((value instanceof Integer)
|| (value instanceof Byte)
|| (value instanceof Character)
|| (value instanceof Short)
|| (value instanceof Boolean)) {
/* covers byte, boolean, char, short, int */
if(value instanceof Boolean)
constString = (value.toString() == "true") ? "1L" : "0L";
else
|| (value instanceof Short)) {
/* covers byte, short, int */
constString = value.toString() + "L";
} else if (value instanceof Boolean) {
constString = ((Boolean) value) ? "1L" : "0L";
} else if (value instanceof Character) {
Character ch = (Character) value;
constString = String.valueOf(((int) ch) & 0xffff) + "L";
} else if (value instanceof Long) {
// Visual C++ supports the i64 suffix, not LL.
if (isWindows)
@ -294,24 +323,19 @@ public abstract class Gen {
/*
* File name and file preamble related operations.
*/
protected void writeFileTop(OutputStream o) {
protected void writeFileTop(OutputStream o) throws Util.Exit {
PrintWriter pw = wrapWriter(o);
pw.println("/* DO NOT EDIT THIS FILE - it is machine generated */" + lineSep +
getIncludes());
}
protected String baseFileName(String clazz) {
StringBuffer f =
new StringBuffer(Mangle.mangle(clazz,
Mangle.Type.CLASS));
if (outDir != null) {
f.insert(0, outDir);
}
return f.toString();
protected String baseFileName(CharSequence className) {
return mangler.mangle(className, Mangle.Type.CLASS);
}
protected String getFileName(String clazz) {
return baseFileName(clazz) + getFileSuffix();
protected FileObject getFileObject(CharSequence className) throws IOException {
String name = baseFileName(className) + getFileSuffix();
return fileManager.getFileForOutput(StandardLocation.SOURCE_OUTPUT, "", name, null);
}
protected String getFileSuffix() {
@ -322,26 +346,39 @@ public abstract class Gen {
* Including super classes' fields.
*/
FieldDoc[] getAllFields(ClassDoc subclazz)
throws ClassNotFoundException {
Vector<FieldDoc> fields = new Vector<FieldDoc>();
ClassDoc cd = null;
Stack<Object> s = new Stack<Object>();
List<VariableElement> getAllFields(TypeElement subclazz) {
List<VariableElement> fields = new ArrayList<VariableElement>();
TypeElement cd = null;
Stack<TypeElement> s = new Stack<TypeElement>();
cd = subclazz;
while (true) {
s.push(cd);
ClassDoc c = cd.superclass();
TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
if (c == null)
break;
cd = c;
}
while (!s.empty()) {
cd = (ClassDoc)s.pop();
fields.addAll(Arrays.asList(cd.fields()));
cd = s.pop();
fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
}
return fields.toArray(new FieldDoc[fields.size()]);
return fields;
}
// c.f. MethodDoc.signature
String signature(ExecutableElement e) {
StringBuffer sb = new StringBuffer("(");
String sep = "";
for (VariableElement p: e.getParameters()) {
sb.append(sep);
sb.append(types.erasure(p.asType()).toString());
sep = ",";
}
sb.append(")");
return sb.toString();
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.javah;
/**
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
* you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class InternalError extends Error {
private static final long serialVersionUID = 8411861562497165022L;
InternalError(String msg, Throwable cause) {
super("Internal error: " + msg);
initCause(cause);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,95 +27,98 @@ package com.sun.tools.javah;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Vector;
import java.util.Enumeration;
import com.sun.javadoc.*;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
/**
* Header file generator for JNI.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Sucheta Dambalkar(Revised)
*/
public class JNI extends Gen {
public JNI(RootDoc root){
super(root);
JNI(Util util) {
super(util);
}
public String getIncludes() {
return "#include <jni.h>";
}
public void write(OutputStream o, ClassDoc clazz)
throws ClassNotFoundException {
String cname = Mangle.mangle(clazz.qualifiedName(), Mangle.Type.CLASS);
public void write(OutputStream o, TypeElement clazz) throws Util.Exit {
String cname = mangler.mangle(clazz.getQualifiedName(), Mangle.Type.CLASS);
PrintWriter pw = wrapWriter(o);
pw.println(guardBegin(cname));
pw.println(cppGuardBegin());
/* Write statics. */
FieldDoc[] classfields = getAllFields(clazz);
List<VariableElement> classfields = getAllFields(clazz);
for (int i = 0; i < classfields.length; i++) {
if (!classfields[i].isStatic())
for (VariableElement v: classfields) {
if (!v.getModifiers().contains(Modifier.STATIC))
continue;
String s = null;
s = defineForStatic(clazz, classfields[i]);
s = defineForStatic(clazz, v);
if (s != null) {
pw.println(s);
}
}
/* Write methods. */
MethodDoc[] classmethods = clazz.methods();
for (int i = 0; i < classmethods.length; i++) {
if(classmethods[i].isNative()){
MethodDoc md = classmethods[i];
Type mtr = classmethods[i].returnType();
String sig = md.signature();
TypeSignature newtypesig = new TypeSignature(root);
String methodName = md.name();
List<ExecutableElement> classmethods = ElementFilter.methodsIn(clazz.getEnclosedElements());
for (ExecutableElement md: classmethods) {
if(md.getModifiers().contains(Modifier.NATIVE)){
TypeMirror mtr = types.erasure(md.getReturnType());
String sig = signature(md);
TypeSignature newtypesig = new TypeSignature(elems);
CharSequence methodName = md.getSimpleName();
boolean longName = false;
for (int j = 0; j < classmethods.length; j++) {
if ((classmethods[j] != md)
&& (methodName.equals(classmethods[j].name()))
&& (classmethods[j].isNative()))
for (ExecutableElement md2: classmethods) {
if ((md2 != md)
&& (methodName.equals(md2.getSimpleName()))
&& (md2.getModifiers().contains(Modifier.NATIVE)))
longName = true;
}
pw.println("/*");
pw.println(" * Class: " + cname);
pw.println(" * Method: " +
Mangle.mangle(methodName, Mangle.Type.FIELDSTUB));
mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr));
pw.println(" */");
pw.println("JNIEXPORT " + jniType(mtr) +
" JNICALL " +
Mangle.mangleMethod(md, root,clazz,
mangler.mangleMethod(md, clazz,
(longName) ?
Mangle.Type.METHOD_JNI_LONG :
Mangle.Type.METHOD_JNI_SHORT));
pw.print(" (JNIEnv *, ");
Parameter[] paramargs = md.parameters();
Type []args =new Type[ paramargs.length];
for(int p = 0; p < paramargs.length; p++){
args[p] = paramargs[p].type();
List<? extends VariableElement> paramargs = md.getParameters();
List<TypeMirror> args = new ArrayList<TypeMirror>();
for (VariableElement p: paramargs) {
args.add(types.erasure(p.asType()));
}
if (md.isStatic())
if (md.getModifiers().contains(Modifier.STATIC))
pw.print("jclass");
else
pw.print("jobject");
if (args.length > 0)
pw.print(", ");
for (int j = 0; j < args.length; j++) {
pw.print(jniType(args[j]));
if (j != (args.length - 1)) {
for (TypeMirror arg: args) {
pw.print(", ");
}
pw.print(jniType(arg));
}
pw.println(");" + lineSep);
}
@ -125,42 +128,54 @@ public class JNI extends Gen {
}
protected final String jniType(Type t){
protected final String jniType(TypeMirror t) throws Util.Exit {
TypeElement throwable = elems.getTypeElement("java.lang.Throwable");
TypeElement jClass = elems.getTypeElement("java.lang.Class");
TypeElement jString = elems.getTypeElement("java.lang.String");
Element tclassDoc = types.asElement(t);
String elmT = t.typeName();
ClassDoc throwable = root.classNamed("java.lang.Throwable");
ClassDoc jClass = root.classNamed("java.lang.Class");
ClassDoc tclassDoc = t.asClassDoc();
if((t.dimension()).indexOf("[]") != -1){
if((t.dimension().indexOf("[][]") != -1)
|| (tclassDoc != null)) return "jobjectArray";
else if(elmT.equals("boolean"))return "jbooleanArray";
else if(elmT.equals("byte"))return "jbyteArray";
else if(elmT.equals("char"))return "jcharArray";
else if(elmT.equals("short"))return "jshortArray";
else if(elmT.equals("int"))return "jintArray";
else if(elmT.equals("long"))return "jlongArray";
else if(elmT.equals("float"))return "jfloatArray";
else if(elmT.equals("double"))return "jdoubleArray";
}else{
if(elmT.equals("void"))return "void";
else if(elmT.equals("String"))return "jstring";
else if(elmT.equals("boolean"))return "jboolean";
else if(elmT.equals("byte"))return "jbyte";
else if(elmT.equals("char"))return "jchar";
else if(elmT.equals("short"))return "jshort";
else if(elmT.equals("int"))return "jint";
else if(elmT.equals("long"))return "jlong";
else if(elmT.equals("float"))return "jfloat";
else if(elmT.equals("double"))return "jdouble";
else if(tclassDoc != null){
if(tclassDoc.subclassOf(throwable)) return "jthrowable";
else if(tclassDoc.subclassOf(jClass)) return "jclass";
else return "jobject";
switch (t.getKind()) {
case ARRAY: {
TypeMirror ct = ((ArrayType) t).getComponentType();
switch (ct.getKind()) {
case BOOLEAN: return "jbooleanArray";
case BYTE: return "jbyteArray";
case CHAR: return "jcharArray";
case SHORT: return "jshortArray";
case INT: return "jintArray";
case LONG: return "jlongArray";
case FLOAT: return "jfloatArray";
case DOUBLE: return "jdoubleArray";
case ARRAY:
case DECLARED: return "jobjectArray";
default: throw new Error(ct.toString());
}
}
Util.bug("jni.unknown.type");
case VOID: return "void";
case BOOLEAN: return "jboolean";
case BYTE: return "jbyte";
case CHAR: return "jchar";
case SHORT: return "jshort";
case INT: return "jint";
case LONG: return "jlong";
case FLOAT: return "jfloat";
case DOUBLE: return "jdouble";
case DECLARED: {
if (tclassDoc.equals(jString))
return "jstring";
else if (types.isAssignable(t, throwable.asType()))
return "jthrowable";
else if (types.isAssignable(t, jClass.asType()))
return "jclass";
else
return "jobject";
}
}
util.bug("jni.unknown.type");
return null; /* dead code. */
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.javah;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
/**
* javah's implementation of JavaFileManager.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
* you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
class JavahFileManager extends JavacFileManager {
private JavahFileManager(Context context, Charset charset) {
super(context, true, charset);
setIgnoreSymbolFile(true);
}
static JavahFileManager create(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
Context javac_context = new Context();
if (dl != null)
javac_context.put(DiagnosticListener.class, dl);
javac_context.put(com.sun.tools.javac.util.Log.outKey, log);
return new JavahFileManager(javac_context, null);
}
void setIgnoreSymbolFile(boolean b) {
ignoreSymbolFile = b;
}
}

View file

@ -0,0 +1,724 @@
/*
* Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.javah;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.SimpleTypeVisitor6;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
/**
* Javah generates support files for native methods.
* Parse commandline options & Invokes javadoc to execute those commands.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Sucheta Dambalkar
* @author Jonathan Gibbons
*/
public class JavahTask implements NativeHeaderTool.NativeHeaderTask {
public class BadArgs extends Exception {
private static final long serialVersionUID = 1479361270874789045L;
BadArgs(String key, Object... args) {
super(JavahTask.this.getMessage(key, args));
this.key = key;
this.args = args;
}
BadArgs showUsage(boolean b) {
showUsage = b;
return this;
}
final String key;
final Object[] args;
boolean showUsage;
}
static abstract class Option {
Option(boolean hasArg, String... aliases) {
this.hasArg = hasArg;
this.aliases = aliases;
}
boolean isHidden() {
return false;
}
boolean matches(String opt) {
for (String a: aliases) {
if (a.equals(opt))
return true;
}
return false;
}
boolean ignoreRest() {
return false;
}
abstract void process(JavahTask task, String opt, String arg) throws BadArgs;
final boolean hasArg;
final String[] aliases;
}
static abstract class HiddenOption extends Option {
HiddenOption(boolean hasArg, String... aliases) {
super(hasArg, aliases);
}
@Override
boolean isHidden() {
return true;
}
}
static Option[] recognizedOptions = {
new Option(true, "-o") {
void process(JavahTask task, String opt, String arg) {
task.ofile = new File(arg);
}
},
new Option(true, "-d") {
void process(JavahTask task, String opt, String arg) {
task.odir = new File(arg);
}
},
new HiddenOption(true, "-td") {
void process(JavahTask task, String opt, String arg) {
// ignored; for backwards compatibility
}
},
new HiddenOption(false, "-stubs") {
void process(JavahTask task, String opt, String arg) {
// ignored; for backwards compatibility
}
},
new Option(false, "-v", "-verbose") {
void process(JavahTask task, String opt, String arg) {
task.verbose = true;
}
},
new Option(false, "-help", "--help", "-?") {
void process(JavahTask task, String opt, String arg) {
task.help = true;
}
},
new HiddenOption(false, "-trace") {
void process(JavahTask task, String opt, String arg) {
task.trace = true;
}
},
new Option(false, "-version") {
void process(JavahTask task, String opt, String arg) {
task.version = true;
}
},
new HiddenOption(false, "-fullversion") {
void process(JavahTask task, String opt, String arg) {
task.fullVersion = true;
}
},
new Option(false, "-jni") {
void process(JavahTask task, String opt, String arg) {
task.jni = true;
}
},
new Option(false, "-force") {
void process(JavahTask task, String opt, String arg) {
task.force = true;
}
},
new HiddenOption(false, "-Xnew") {
void process(JavahTask task, String opt, String arg) {
// we're already using the new javah
}
},
new HiddenOption(false, "-old") {
void process(JavahTask task, String opt, String arg) {
task.old = true;
}
},
new HiddenOption(false, "-llni", "-Xllni") {
void process(JavahTask task, String opt, String arg) {
task.llni = true;
}
},
new HiddenOption(false, "-llnidouble") {
void process(JavahTask task, String opt, String arg) {
task.llni = true;
task.doubleAlign = true;
}
},
};
JavahTask() {
}
JavahTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes) {
this();
this.log = getPrintWriterForWriter(out);
this.fileManager = fileManager;
this.diagnosticListener = diagnosticListener;
try {
handleOptions(options, false);
} catch (BadArgs e) {
throw new IllegalArgumentException(e.getMessage());
}
this.classes = new ArrayList<String>();
for (String classname: classes) {
classname.getClass(); // null-check
this.classes.add(classname);
}
}
public void setLocale(Locale locale) {
if (locale == null)
locale = Locale.getDefault();
task_locale = locale;
}
public void setLog(PrintWriter log) {
this.log = log;
}
public void setLog(OutputStream s) {
setLog(getPrintWriterForStream(s));
}
static PrintWriter getPrintWriterForStream(OutputStream s) {
return new PrintWriter(s, true);
}
static PrintWriter getPrintWriterForWriter(Writer w) {
if (w == null)
return getPrintWriterForStream(null);
else if (w instanceof PrintWriter)
return (PrintWriter) w;
else
return new PrintWriter(w, true);
}
public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
diagnosticListener = dl;
}
public void setDiagnosticListener(OutputStream s) {
setDiagnosticListener(getDiagnosticListenerForStream(s));
}
private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
}
private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
final PrintWriter pw = getPrintWriterForWriter(w);
return new DiagnosticListener<JavaFileObject> () {
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
pw.print(getMessage("err.prefix"));
pw.print(" ");
}
pw.println(diagnostic.getMessage(null));
}
};
}
int run(String[] args) {
try {
handleOptions(args);
boolean ok = run();
return ok ? 0 : 1;
} catch (BadArgs e) {
diagnosticListener.report(createDiagnostic(e.key, e.args));
return 1;
} catch (InternalError e) {
diagnosticListener.report(createDiagnostic("err.internal.error", e.getMessage()));
return 1;
} finally {
log.flush();
}
}
public void handleOptions(String[] args) throws BadArgs {
handleOptions(Arrays.asList(args), true);
}
private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
if (log == null) {
log = getPrintWriterForStream(System.out);
if (diagnosticListener == null)
diagnosticListener = getDiagnosticListenerForStream(System.err);
} else {
if (diagnosticListener == null)
diagnosticListener = getDiagnosticListenerForWriter(log);
}
if (fileManager == null)
fileManager = getDefaultFileManager(diagnosticListener, log);
Iterator<String> iter = args.iterator();
if (!iter.hasNext())
help = true;
while (iter.hasNext()) {
String arg = iter.next();
if (arg.startsWith("-"))
handleOption(arg, iter);
else if (allowClasses) {
if (classes == null)
classes = new ArrayList<String>();
classes.add(arg);
while (iter.hasNext())
classes.add(iter.next());
} else
throw new BadArgs("err.unknown.option", arg).showUsage(true);
}
if ((classes == null || classes.size() == 0) &&
!(help || version || fullVersion)) {
throw new BadArgs("err.no.classes.specified");
}
if (jni && llni)
throw new BadArgs("jni.llni.mixed");
if (odir != null && ofile != null)
throw new BadArgs("dir.file.mixed");
}
private void handleOption(String name, Iterator<String> rest) throws BadArgs {
for (Option o: recognizedOptions) {
if (o.matches(name)) {
if (o.hasArg) {
if (rest.hasNext())
o.process(this, name, rest.next());
else
throw new BadArgs("err.missing.arg", name).showUsage(true);
} else
o.process(this, name, null);
if (o.ignoreRest()) {
while (rest.hasNext())
rest.next();
}
return;
}
}
if (fileManager.handleOption(name, rest))
return;
throw new BadArgs("err.unknown.option", name).showUsage(true);
}
public Boolean call() {
return run();
}
public boolean run() throws Util.Exit {
Util util = new Util(log, diagnosticListener);
if (help) {
showHelp();
return true;
}
if (version || fullVersion) {
showVersion(fullVersion);
return true;
}
util.verbose = verbose;
Gen g;
if (llni)
g = new LLNI(doubleAlign, util);
else {
// if (stubs)
// throw new BadArgs("jni.no.stubs");
g = new JNI(util);
}
if (ofile != null) {
if (!(fileManager instanceof StandardJavaFileManager)) {
diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-o"));
return false;
}
Iterable<? extends JavaFileObject> iter =
((StandardJavaFileManager) fileManager).getJavaFileObjectsFromFiles(Collections.singleton(ofile));
JavaFileObject fo = iter.iterator().next();
g.setOutFile(fo);
} else {
if (odir != null) {
if (!(fileManager instanceof StandardJavaFileManager)) {
diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-d"));
return false;
}
if (!odir.exists())
if (!odir.mkdirs())
util.error("cant.create.dir", odir.toString());
try {
((StandardJavaFileManager) fileManager).setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(odir));
} catch (IOException e) {
Object msg = e.getLocalizedMessage();
if (msg == null) {
msg = e;
}
diagnosticListener.report(createDiagnostic("err.ioerror", odir, msg));
return false;
}
}
g.setFileManager(fileManager);
}
/*
* Force set to false will turn off smarts about checking file
* content before writing.
*/
g.setForce(force);
if (fileManager instanceof JavahFileManager)
((JavahFileManager) fileManager).setIgnoreSymbolFile(true);
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
List<String> opts = Arrays.asList("-proc:only");
CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, internalize(classes), null);
JavahProcessor p = new JavahProcessor(g);
t.setProcessors(Collections.singleton(p));
boolean ok = t.call();
if (p.exit != null)
throw new Util.Exit(p.exit);
return ok;
}
private List<String> internalize(List<String> classes) {
List<String> l = new ArrayList<String>();
for (String c: classes) {
l.add(c.replace('$', '.'));
}
return l;
}
private List<File> pathToFiles(String path) {
List<File> files = new ArrayList<File>();
for (String f: path.split(File.pathSeparator)) {
if (f.length() > 0)
files.add(new File(f));
}
return files;
}
static StandardJavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
return JavahFileManager.create(dl, log);
}
private void showHelp() {
log.println(getMessage("main.usage", progname));
for (Option o: recognizedOptions) {
if (o.isHidden())
continue;
String name = o.aliases[0].substring(1); // there must always be at least one name
log.println(getMessage("main.opt." + name));
}
String[] fmOptions = { "-classpath", "-bootclasspath" };
for (String o: fmOptions) {
if (fileManager.isSupportedOption(o) == -1)
continue;
String name = o.substring(1);
log.println(getMessage("main.opt." + name));
}
log.println(getMessage("main.usage.foot"));
}
private void showVersion(boolean full) {
log.println(version(full ? "full" : "release"));
}
private static final String versionRBName = "com.sun.tools.javah.resources.version";
private static ResourceBundle versionRB;
private String version(String key) {
// key=version: mm.nn.oo[-milestone]
// key=full: mm.mm.oo[-milestone]-build
if (versionRB == null) {
try {
versionRB = ResourceBundle.getBundle(versionRBName);
} catch (MissingResourceException e) {
return getMessage("version.resource.missing", System.getProperty("java.version"));
}
}
try {
return versionRB.getString(key);
}
catch (MissingResourceException e) {
return getMessage("version.unknown", System.getProperty("java.version"));
}
}
private Diagnostic<JavaFileObject> createDiagnostic(final String key, final Object... args) {
return new Diagnostic<JavaFileObject>() {
public Kind getKind() {
return Diagnostic.Kind.ERROR;
}
public JavaFileObject getSource() {
return null;
}
public long getPosition() {
return Diagnostic.NOPOS;
}
public long getStartPosition() {
return Diagnostic.NOPOS;
}
public long getEndPosition() {
return Diagnostic.NOPOS;
}
public long getLineNumber() {
return Diagnostic.NOPOS;
}
public long getColumnNumber() {
return Diagnostic.NOPOS;
}
public String getCode() {
return key;
}
public String getMessage(Locale locale) {
return JavahTask.this.getMessage(locale, key, args);
}
};
}
private String getMessage(String key, Object... args) {
return getMessage(task_locale, key, args);
}
private String getMessage(Locale locale, String key, Object... args) {
if (bundles == null) {
// could make this a HashMap<Locale,SoftReference<ResourceBundle>>
// and for efficiency, keep a hard reference to the bundle for the task
// locale
bundles = new HashMap<Locale, ResourceBundle>();
}
if (locale == null)
locale = Locale.getDefault();
ResourceBundle b = bundles.get(locale);
if (b == null) {
try {
b = ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n", locale);
bundles.put(locale, b);
} catch (MissingResourceException e) {
throw new InternalError("Cannot find javah resource bundle for locale " + locale, e);
}
}
try {
return MessageFormat.format(b.getString(key), args);
} catch (MissingResourceException e) {
return key;
//throw new InternalError(e, key);
}
}
File ofile;
File odir;
String bootcp;
String usercp;
List<String> classes;
boolean verbose;
boolean help;
boolean trace;
boolean version;
boolean fullVersion;
boolean jni;
boolean llni;
boolean doubleAlign;
boolean force;
boolean old;
PrintWriter log;
JavaFileManager fileManager;
DiagnosticListener<? super JavaFileObject> diagnosticListener;
Locale task_locale;
Map<Locale, ResourceBundle> bundles;
private static final String progname = "javah";
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
class JavahProcessor extends AbstractProcessor {
JavahProcessor(Gen g) {
this.g = g;
}
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Messager messager = processingEnv.getMessager();
Set<TypeElement> classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements()));
if (classes.size() > 0) {
checkMethodParameters(classes);
g.setProcessingEnvironment(processingEnv);
g.setClasses(classes);
try {
g.run();
} catch (ClassNotFoundException cnfe) {
messager.printMessage(Diagnostic.Kind.ERROR, getMessage("class.not.found", cnfe.getMessage()));
} catch (IOException ioe) {
messager.printMessage(Diagnostic.Kind.ERROR, getMessage("io.exception", ioe.getMessage()));
} catch (Util.Exit e) {
exit = e;
}
}
return true;
}
private Set<TypeElement> getAllClasses(Set<? extends TypeElement> classes) {
Set<TypeElement> allClasses = new LinkedHashSet<TypeElement>();
getAllClasses0(classes, allClasses);
return allClasses;
}
private void getAllClasses0(Iterable<? extends TypeElement> classes, Set<TypeElement> allClasses) {
for (TypeElement c: classes) {
allClasses.add(c);
getAllClasses0(ElementFilter.typesIn(c.getEnclosedElements()), allClasses);
}
}
// 4942232:
// check that classes exist for all the parameters of native methods
private void checkMethodParameters(Set<TypeElement> classes) {
Types types = processingEnv.getTypeUtils();
for (TypeElement te: classes) {
for (ExecutableElement ee: ElementFilter.methodsIn(te.getEnclosedElements())) {
for (VariableElement ve: ee.getParameters()) {
TypeMirror tm = ve.asType();
checkMethodParametersVisitor.visit(tm, types);
}
}
}
}
private TypeVisitor<Void,Types> checkMethodParametersVisitor =
new SimpleTypeVisitor6<Void,Types>() {
@Override
public Void visitArray(ArrayType t, Types types) {
visit(t.getComponentType(), types);
return null;
}
@Override
public Void visitDeclared(DeclaredType t, Types types) {
t.asElement().getKind(); // ensure class exists
for (TypeMirror st: types.directSupertypes(t))
visit(st, types);
return null;
}
};
private Gen g;
private Util.Exit exit;
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.javah;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Locale;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
/*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class JavahTool implements NativeHeaderTool {
public NativeHeaderTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes) {
return new JavahTask(out, fileManager, diagnosticListener, options, classes);
}
public StandardJavaFileManager getStandardFileManager(DiagnosticListener<? super JavaFileObject> diagnosticListener, Locale locale, Charset charset) {
return JavahTask.getDefaultFileManager(diagnosticListener, null);
}
public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) {
JavahTask t = new JavahTask(
JavahTask.getPrintWriterForStream(out),
null,
null,
Arrays.asList(arguments),
null);
return (t.run() ? 0 : 1);
}
public Set<SourceVersion> getSourceVersions() {
return EnumSet.allOf(SourceVersion.class);
}
public int isSupportedOption(String option) {
JavahTask.Option[] options = JavahTask.recognizedOptions;
for (int i = 0; i < options.length; i++) {
if (options[i].matches(option))
return (options[i].hasArg ? 1 : 0);
}
return -1;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,49 +26,65 @@
package com.sun.tools.javah;
import java.io.File;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Hashtable;
import com.sun.javadoc.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/*
import java.util.Set;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.SimpleTypeVisitor6;
/*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Sucheta Dambalkar(Revised)
*/
public class LLNI extends Gen {
protected final char pathChar = File.separatorChar;
protected final char innerDelim = '$'; /* For inner classes */
protected Hashtable<Object, Object> doneHandleTypes;
MemberDoc []fields;
MemberDoc [] methods;
protected Set<String> doneHandleTypes;
List<VariableElement> fields;
List<ExecutableElement> methods;
private boolean doubleAlign;
private int padFieldNum = 0;
LLNI(boolean doubleAlign, RootDoc root) {
super(root);
LLNI(boolean doubleAlign, Util util) {
super(util);
this.doubleAlign = doubleAlign;
}
protected String getIncludes() {
return "";
}
protected void write(OutputStream o, ClassDoc clazz)
throws ClassNotFoundException {
String cname = mangleClassName(clazz.qualifiedName());
protected void write(OutputStream o, TypeElement clazz) throws Util.Exit {
String cname = mangleClassName(clazz.getQualifiedName().toString());
PrintWriter pw = wrapWriter(o);
fields = clazz.fields();
methods = clazz.methods();
fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
methods = ElementFilter.methodsIn(clazz.getEnclosedElements());
generateDeclsForClass(pw, clazz, cname);
// FIXME check if errors occurred on the PrintWriter and throw exception if so
}
protected void generateDeclsForClass(PrintWriter pw,
ClassDoc clazz, String cname)
throws ClassNotFoundException {
doneHandleTypes = new Hashtable<Object, Object>();
TypeElement clazz, String cname) throws Util.Exit {
doneHandleTypes = new HashSet<String>();
/* The following handle types are predefined in "typedefs.h". Suppress
inclusion in the output by generating them "into the blue" here. */
genHandleType(null, "java.lang.Class");
@ -79,7 +95,7 @@ public class LLNI extends Gen {
genHandleType(null, "java.lang.ThreadGroup");
genHandleType(null, "java.lang.Throwable");
pw.println("/* LLNI Header for class " + clazz.qualifiedName() + " */" + lineSep);
pw.println("/* LLNI Header for class " + clazz.getQualifiedName() + " */" + lineSep);
pw.println("#ifndef _Included_" + cname);
pw.println("#define _Included_" + cname);
pw.println("#include \"typedefs.h\"");
@ -94,8 +110,8 @@ public class LLNI extends Gen {
protected void genHandleType(PrintWriter pw, String clazzname) {
String cname = mangleClassName(clazzname);
if (!doneHandleTypes.containsKey(cname)) {
doneHandleTypes.put(cname, cname);
if (!doneHandleTypes.contains(cname)) {
doneHandleTypes.add(cname);
if (pw != null) {
pw.println("#ifndef DEFINED_" + cname);
pw.println(" #define DEFINED_" + cname);
@ -107,31 +123,29 @@ public class LLNI extends Gen {
protected String mangleClassName(String s) {
return s.replace('.', '_')
.replace(pathChar, '_')
.replace('/', '_')
.replace(innerDelim, '_');
}
protected void forwardDecls(PrintWriter pw, ClassDoc clazz)
throws ClassNotFoundException {
ClassDoc clazzfield = null;
if (clazz.qualifiedName().equals("java.lang.Object"))
protected void forwardDecls(PrintWriter pw, TypeElement clazz) {
TypeElement object = elems.getTypeElement("java.lang.Object");
if (clazz.equals(object))
return;
genHandleType(pw, clazz.qualifiedName());
ClassDoc superClass = clazz.superclass();
if(superClass != null){
String superClassName = superClass.qualifiedName();
genHandleType(pw, clazz.getQualifiedName().toString());
TypeElement superClass = (TypeElement) (types.asElement(clazz.getSuperclass()));
if (superClass != null) {
String superClassName = superClass.getQualifiedName().toString();
forwardDecls(pw, superClass);
}
for (int i = 0; i < fields.length; i++) {
FieldDoc field = (FieldDoc)fields[i];
for (VariableElement field: fields) {
if (!field.isStatic()) {
Type t = field.type();
String tname = t.qualifiedTypeName();
TypeSignature newTypeSig = new TypeSignature(root);
if (!field.getModifiers().contains(Modifier.STATIC)) {
TypeMirror t = types.erasure(field.asType());
TypeSignature newTypeSig = new TypeSignature(elems);
String tname = newTypeSig.qualifiedTypeName(t);
String sig = newTypeSig.getTypeSignature(tname);
if (sig.charAt(0) != '[')
@ -139,13 +153,12 @@ public class LLNI extends Gen {
}
}
for (int i = 0; i < methods.length; i++) {
MethodDoc method = (MethodDoc)methods[i];
for (ExecutableElement method: methods) {
if (method.isNative()) {
Type retType = method.returnType();
String typesig = method.signature();
TypeSignature newTypeSig = new TypeSignature(root);
if (method.getModifiers().contains(Modifier.NATIVE)) {
TypeMirror retType = types.erasure(method.getReturnType());
String typesig = signature(method);
TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(typesig, retType);
if (sig.charAt(0) != '[')
@ -173,10 +186,9 @@ public class LLNI extends Gen {
}
protected void structSectionForClass(PrintWriter pw,
ClassDoc jclazz, String cname)
throws ClassNotFoundException {
TypeElement jclazz, String cname) {
String jname = jclazz.qualifiedName();
String jname = jclazz.getQualifiedName().toString();
if (cname.equals("java_lang_Object")) {
pw.println("/* struct java_lang_Object is defined in typedefs.h. */");
@ -207,8 +219,8 @@ public class LLNI extends Gen {
public boolean bottomMost;
public boolean printedOne = false;
FieldDefsRes(ClassDoc clazz, FieldDefsRes parent, boolean bottomMost) {
this.className = clazz.qualifiedName();
FieldDefsRes(TypeElement clazz, FieldDefsRes parent, boolean bottomMost) {
this.className = clazz.getQualifiedName().toString();
this.parent = parent;
this.bottomMost = bottomMost;
int byteSize = 0;
@ -218,9 +230,8 @@ public class LLNI extends Gen {
}
/* Returns "true" iff added a field. */
private boolean doField(FieldDefsRes res, FieldDoc field,
String cname, boolean padWord)
throws ClassNotFoundException {
private boolean doField(FieldDefsRes res, VariableElement field,
String cname, boolean padWord) {
String fieldDef = addStructMember(field, cname, padWord);
if (fieldDef != null) {
@ -242,16 +253,14 @@ public class LLNI extends Gen {
return false;
}
private int doTwoWordFields(FieldDefsRes res, ClassDoc clazz,
int offset, String cname, boolean padWord)
throws ClassNotFoundException {
private int doTwoWordFields(FieldDefsRes res, TypeElement clazz,
int offset, String cname, boolean padWord) {
boolean first = true;
FieldDoc[] fields = clazz.fields();
List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
for (int i = 0; i <fields.length; i++) {
FieldDoc field = fields[i];
String tc =field.type().typeName();
boolean twoWords = (tc.equals("long") || tc.equals("double"));
for (VariableElement field: fields) {
TypeKind tk = field.asType().getKind();
boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
if (twoWords && doField(res, field, cname, first && padWord)) {
offset += 8; first = false;
}
@ -259,22 +268,21 @@ public class LLNI extends Gen {
return offset;
}
protected String fieldDefs(ClassDoc clazz, String cname)
throws ClassNotFoundException {
String fieldDefs(TypeElement clazz, String cname) {
FieldDefsRes res = fieldDefs(clazz, cname, true);
return res.s;
}
protected FieldDefsRes fieldDefs(ClassDoc clazz, String cname,
boolean bottomMost)
throws ClassNotFoundException {
FieldDefsRes fieldDefs(TypeElement clazz, String cname,
boolean bottomMost){
FieldDefsRes res;
int offset;
boolean didTwoWordFields = false;
ClassDoc superclazz = clazz.superclass();
TypeElement superclazz = (TypeElement) types.asElement(clazz.getSuperclass());
if (superclazz != null) {
String supername = superclazz.qualifiedName();
String supername = superclazz.getQualifiedName().toString();
res = new FieldDefsRes(clazz,
fieldDefs(superclazz, cname, false),
bottomMost);
@ -284,18 +292,17 @@ public class LLNI extends Gen {
offset = 0;
}
FieldDoc[] fields = clazz.fields();
List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
for (int i = 0; i < fields.length; i++) {
FieldDoc field = fields[i];
for (VariableElement field: fields) {
if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) {
offset = doTwoWordFields(res, clazz, offset, cname, false);
didTwoWordFields = true;
}
String tc = field.type().typeName();
boolean twoWords = (tc.equals("long") ||tc.equals("double"));
TypeKind tk = field.asType().getKind();
boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
if (!doubleAlign || !twoWords) {
if (doField(res, field, cname, false)) offset += 4;
@ -313,19 +320,19 @@ public class LLNI extends Gen {
}
/* OVERRIDE: This method handles instance fields */
protected String addStructMember(FieldDoc member, String cname,
boolean padWord)
throws ClassNotFoundException {
protected String addStructMember(VariableElement member, String cname,
boolean padWord) {
String res = null;
if (member.isStatic()) {
if (member.getModifiers().contains(Modifier.STATIC)) {
res = addStaticStructMember(member, cname);
// if (res == null) /* JNI didn't handle it, print comment. */
// res = " /* Inaccessible static: " + member + " */" + lineSep;
} else {
TypeMirror mt = types.erasure(member.asType());
if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep;
res = " " + llniType(member.type(), false, false) + " " + llniFieldName(member);
if (isLongOrDouble(member.type())) res = res + "[2]";
res = " " + llniType(mt, false, false) + " " + llniFieldName(member);
if (isLongOrDouble(mt)) res = res + "[2]";
res = res + ";" + lineSep;
}
return res;
@ -337,36 +344,42 @@ public class LLNI extends Gen {
/*
* This method only handles static final fields.
*/
protected String addStaticStructMember(FieldDoc field, String cname)
throws ClassNotFoundException {
protected String addStaticStructMember(VariableElement field, String cname) {
String res = null;
Object exp = null;
if (!field.isStatic())
if (!field.getModifiers().contains(Modifier.STATIC))
return res;
if (!field.isFinal())
if (!field.getModifiers().contains(Modifier.FINAL))
return res;
exp = field.constantValue();
exp = field.getConstantValue();
if (exp != null) {
/* Constant. */
String cn = cname + "_" + field.name();
String cn = cname + "_" + field.getSimpleName();
String suffix = null;
long val = 0;
/* Can only handle int, long, float, and double fields. */
if (exp instanceof Integer) {
if (exp instanceof Byte
|| exp instanceof Short
|| exp instanceof Integer) {
suffix = "L";
val = ((Integer)exp).intValue();
val = ((Number)exp).intValue();
}
if (exp instanceof Long) {
else if (exp instanceof Long) {
// Visual C++ supports the i64 suffix, not LL
suffix = isWindows ? "i64" : "LL";
val = ((Long)exp).longValue();
}
if (exp instanceof Float) suffix = "f";
if (exp instanceof Double) suffix = "";
else if (exp instanceof Float) suffix = "f";
else if (exp instanceof Double) suffix = "";
else if (exp instanceof Character) {
suffix = "L";
Character ch = (Character) exp;
val = ((int) ch) & 0xffff;
}
if (suffix != null) {
// Some compilers will generate a spurious warning
// for the integer constants for Integer.MIN_VALUE
@ -376,9 +389,12 @@ public class LLNI extends Gen {
res = " #undef " + cn + lineSep
+ " #define " + cn
+ " (" + (val + 1) + suffix + "-1)" + lineSep;
} else if (suffix.equals("L") || suffix.endsWith("LL")) {
res = " #undef " + cn + lineSep
+ " #define " + cn + " " + val + suffix + lineSep;
} else {
res = " #undef " + cn + lineSep
+ " #define " + cn + " "+ exp.toString() + suffix + lineSep;
+ " #define " + cn + " " + exp + suffix + lineSep;
}
}
}
@ -386,8 +402,8 @@ public class LLNI extends Gen {
}
protected void methodSectionForClass(PrintWriter pw,
ClassDoc clazz, String cname)
throws ClassNotFoundException {
TypeElement clazz, String cname)
throws Util.Exit {
String methods = methodDecls(clazz, cname);
if (methods.length() != 0) {
@ -402,81 +418,77 @@ public class LLNI extends Gen {
}
}
protected String methodDecls(ClassDoc clazz, String cname)
throws ClassNotFoundException {
protected String methodDecls(TypeElement clazz, String cname) throws Util.Exit {
String res = "";
for (int i = 0; i < methods.length; i++) {
MethodDoc method = (MethodDoc)methods[i];
if (method.isNative())
for (ExecutableElement method: methods) {
if (method.getModifiers().contains(Modifier.NATIVE))
res = res + methodDecl(method, clazz, cname);
}
return res;
}
protected String methodDecl(MethodDoc method,
ClassDoc clazz, String cname)
throws ClassNotFoundException {
protected String methodDecl(ExecutableElement method,
TypeElement clazz, String cname)
throws Util.Exit {
String res = null;
Type retType = method.returnType();
String typesig = method.signature();
TypeSignature newTypeSig = new TypeSignature(root);
TypeMirror retType = types.erasure(method.getReturnType());
String typesig = signature(method);
TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(typesig, retType);
boolean longName = needLongName(method, clazz);
if (sig.charAt(0) != '(')
Util.error("invalid.method.signature", sig);
util.error("invalid.method.signature", sig);
res = "JNIEXPORT " + jniType(retType) + " JNICALL" + lineSep + jniMethodName(method, cname, longName)
+ "(JNIEnv *, " + cRcvrDecl(method, cname);
Parameter[] params = method.parameters();
Type argTypes[] = new Type[params.length];
for(int p = 0; p < params.length; p++){
argTypes[p] = params[p].type();
List<? extends VariableElement> params = method.getParameters();
List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
for (VariableElement p: params){
argTypes.add(types.erasure(p.asType()));
}
/* It would have been nice to include the argument names in the
declaration, but there seems to be a bug in the "BinaryField"
class, causing the getArguments() method to return "null" for
most (non-constructor) methods. */
for (int i = 0; i < argTypes.length; i++)
res = res + ", " + jniType(argTypes[i]);
for (TypeMirror argType: argTypes)
res = res + ", " + jniType(argType);
res = res + ");" + lineSep;
return res;
}
protected final boolean needLongName(MethodDoc method,
ClassDoc clazz)
throws ClassNotFoundException {
String methodName = method.name();
for (int i = 0; i < methods.length; i++) {
MethodDoc memberMethod = (MethodDoc) methods[i];
protected final boolean needLongName(ExecutableElement method,
TypeElement clazz) {
Name methodName = method.getSimpleName();
for (ExecutableElement memberMethod: methods) {
if ((memberMethod != method) &&
memberMethod.isNative() && (methodName == memberMethod.name()))
memberMethod.getModifiers().contains(Modifier.NATIVE) &&
(methodName.equals(memberMethod.getSimpleName())))
return true;
}
return false;
}
protected final String jniMethodName(MethodDoc method, String cname,
protected final String jniMethodName(ExecutableElement method, String cname,
boolean longName) {
String res = "Java_" + cname + "_" + method.name();
String res = "Java_" + cname + "_" + method.getSimpleName();
if (longName) {
Type mType = method.returnType();
Parameter[] params = method.parameters();
Type argTypes[] = new Type[params.length];
for(int p = 0; p < params.length; p++){
argTypes[p] = params[p].type();
TypeMirror mType = types.erasure(method.getReturnType());
List<? extends VariableElement> params = method.getParameters();
List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
for (VariableElement param: params) {
argTypes.add(types.erasure(param.asType()));
}
res = res + "__";
for (int i = 0; i < argTypes.length; i++){
Type t = argTypes[i];
String tname = t.typeName();
TypeSignature newTypeSig = new TypeSignature(root);
for (TypeMirror t: argTypes) {
String tname = t.toString();
TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(tname);
res = res + nameToIdentifier(sig);
}
@ -484,88 +496,143 @@ public class LLNI extends Gen {
return res;
}
protected final String jniType(Type t) {
String elmT =t.typeName();
if (t.dimension().indexOf("[]") != -1) {
if(elmT.equals("boolean"))return "jbooleanArray";
else if(elmT.equals("byte"))return "jbyteArray";
else if(elmT.equals("char"))return "jcharArray";
else if(elmT.equals("short"))return "jshortArray";
else if(elmT.equals("int"))return "jintArray";
else if(elmT.equals("long"))return "jlongArray";
else if(elmT.equals("float"))return "jfloatArray";
else if(elmT.equals("double"))return "jdoubleArray";
else if((t.dimension().indexOf("[][]") != -1) || (t.asClassDoc() != null)) return "jobjectArray";
} else {
if(elmT.equals("void"))return "void";
else if(elmT.equals("boolean"))return "jboolean";
else if(elmT.equals("byte"))return "jbyte";
else if(elmT.equals("char"))return "jchar";
else if(elmT.equals("short"))return "jshort";
else if(elmT.equals("int"))return "jint";
else if(elmT.equals("long"))return "jlong";
else if(elmT.equals("float"))return "jfloat";
else if(elmT.equals("double"))return "jdouble";
else if (t.asClassDoc() != null) {
if (elmT.equals("String"))
// copied from JNI.java
protected final String jniType(TypeMirror t) throws Util.Exit {
TypeElement throwable = elems.getTypeElement("java.lang.Throwable");
TypeElement jClass = elems.getTypeElement("java.lang.Class");
TypeElement jString = elems.getTypeElement("java.lang.String");
Element tclassDoc = types.asElement(t);
switch (t.getKind()) {
case ARRAY: {
TypeMirror ct = ((ArrayType) t).getComponentType();
switch (ct.getKind()) {
case BOOLEAN: return "jbooleanArray";
case BYTE: return "jbyteArray";
case CHAR: return "jcharArray";
case SHORT: return "jshortArray";
case INT: return "jintArray";
case LONG: return "jlongArray";
case FLOAT: return "jfloatArray";
case DOUBLE: return "jdoubleArray";
case ARRAY:
case DECLARED: return "jobjectArray";
default: throw new Error(ct.toString());
}
}
case VOID: return "void";
case BOOLEAN: return "jboolean";
case BYTE: return "jbyte";
case CHAR: return "jchar";
case SHORT: return "jshort";
case INT: return "jint";
case LONG: return "jlong";
case FLOAT: return "jfloat";
case DOUBLE: return "jdouble";
case DECLARED: {
if (tclassDoc.equals(jString))
return "jstring";
else if (t.asClassDoc().subclassOf(root.classNamed("java.lang.Class")))
else if (types.isAssignable(t, throwable.asType()))
return "jthrowable";
else if (types.isAssignable(t, jClass.asType()))
return "jclass";
else
return "jobject";
}
}
Util.bug("jni.unknown.type");
util.bug("jni.unknown.type");
return null; /* dead code. */
}
protected String llniType(Type t, boolean handleize, boolean longDoubleOK) {
protected String llniType(TypeMirror t, boolean handleize, boolean longDoubleOK) {
String res = null;
String elmt = t.typeName();
if (t.dimension().indexOf("[]") != -1) {
if((t.dimension().indexOf("[][]") != -1)
|| (t.asClassDoc() != null)) res = "IArrayOfRef";
else if(elmt.equals("boolean")) res = "IArrayOfBoolean";
else if(elmt.equals("byte")) res = "IArrayOfByte";
else if(elmt.equals("char")) res = "IArrayOfChar";
else if(elmt.equals("int")) res = "IArrayOfInt";
else if(elmt.equals("long")) res = "IArrayOfLong";
else if(elmt.equals("float")) res = "IArrayOfFloat";
else if(elmt.equals("double")) res = "IArrayOfDouble";
if (!handleize) res = "DEREFERENCED_" + res;
} else {
if(elmt.equals("void")) res = "void";
else if( (elmt.equals("boolean")) || (elmt.equals("byte"))
||(elmt.equals("char")) || (elmt.equals("short"))
|| (elmt.equals("int"))) res = "java_int";
else if(elmt.equals("long")) res = longDoubleOK
? "java_long" : "val32 /* java_long */";
else if(elmt.equals("float")) res = "java_float";
else if(elmt.equals("double")) res = res = longDoubleOK
? "java_double" : "val32 /* java_double */";
else if(t.asClassDoc() != null) {
res = "I" + mangleClassName(t.asClassDoc().qualifiedName());
if (!handleize) res = "DEREFERENCED_" + res;
switch (t.getKind()) {
case ARRAY: {
TypeMirror ct = ((ArrayType) t).getComponentType();
switch (ct.getKind()) {
case BOOLEAN: res = "IArrayOfBoolean"; break;
case BYTE: res = "IArrayOfByte"; break;
case CHAR: res = "IArrayOfChar"; break;
case SHORT: res = "IArrayOfShort"; break;
case INT: res = "IArrayOfInt"; break;
case LONG: res = "IArrayOfLong"; break;
case FLOAT: res = "IArrayOfFloat"; break;
case DOUBLE: res = "IArrayOfDouble"; break;
case ARRAY:
case DECLARED: res = "IArrayOfRef"; break;
default: throw new Error(ct.getKind() + " " + ct);
}
if (!handleize) res = "DEREFERENCED_" + res;
break;
}
case VOID:
res = "void";
break;
case BOOLEAN:
case BYTE:
case CHAR:
case SHORT:
case INT:
res = "java_int" ;
break;
case LONG:
res = longDoubleOK ? "java_long" : "val32 /* java_long */";
break;
case FLOAT:
res = "java_float";
break;
case DOUBLE:
res = longDoubleOK ? "java_double" : "val32 /* java_double */";
break;
case DECLARED:
TypeElement e = (TypeElement) types.asElement(t);
res = "I" + mangleClassName(e.getQualifiedName().toString());
if (!handleize) res = "DEREFERENCED_" + res;
break;
default:
throw new Error(t.getKind() + " " + t); // FIXME
}
return res;
}
protected final String cRcvrDecl(MemberDoc field, String cname) {
return (field.isStatic() ? "jclass" : "jobject");
protected final String cRcvrDecl(Element field, String cname) {
return (field.getModifiers().contains(Modifier.STATIC) ? "jclass" : "jobject");
}
protected String maskName(String s) {
return "LLNI_mask(" + s + ")";
}
protected String llniFieldName(MemberDoc field) {
return maskName(field.name());
protected String llniFieldName(VariableElement field) {
return maskName(field.getSimpleName().toString());
}
protected final boolean isLongOrDouble(Type t) {
String tc = t.typeName();
return (tc.equals("long") || tc.equals("double"));
protected final boolean isLongOrDouble(TypeMirror t) {
TypeVisitor<Boolean,Void> v = new SimpleTypeVisitor6<Boolean,Void>() {
public Boolean defaultAction(TypeMirror t, Void p){
return false;
}
public Boolean visitArray(ArrayType t, Void p) {
return visit(t.getComponentType(), p);
}
public Boolean visitPrimitive(PrimitiveType t, Void p) {
TypeKind tk = t.getKind();
return (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
}
};
return v.visit(t, null);
}
/* Do unicode to ansi C identifier conversion.
@ -602,3 +669,4 @@ public class LLNI extends Gen {
return false;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,134 +23,39 @@
* have any questions.
*/
package com.sun.tools.javah;
import java.io.*;
import java.io.PrintWriter;
/**
* Javah generates support files for native methods.
* Parse commandline options & Invokes javadoc to execute those commands.
* Main entry point.
*
* @author Sucheta Dambalkar
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
* you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Main{
/*
* Parse arguments given for javah to give proper error messages.
public class Main {
/**
* Main entry point for the launcher.
* Note: This method calls System.exit.
* @param args command line arguments
*/
public static void main(String[] args){
if (args.length == 0) {
Util.usage(1);
}
for ( int i = 0; i < args.length; i++) {
if (args[i].equals("-o")) {
i++;
if(i >= args.length){
Util.usage(1);
}else if(args[i].charAt(0) == '-'){
Util.error("no.outputfile.specified");
}else if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-d")) {
i++;
if(i >= args.length){
Util.usage(1);
}else if(args[i].charAt(0) == '-') {
Util.error("no.outputdir.specified");
}else if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-td")) {
/* Ignored. Generate tmp files to memory. */
i++;
if (i == args.length)
Util.usage(1);
} else if (args[i].equals("-stubs")) {
if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-v") || args[i].equals("-verbose")) {
if((i+1) >= args.length){
Util.error("no.classes.specified");
}
args[i] = "-verbose";
} else if ((args[i].equals("-help")) || (args[i].equals("--help"))
|| (args[i].equals("-?")) || (args[i].equals("-h"))) {
Util.usage(0);
} else if (args[i].equals("-trace")) {
System.err.println(Util.getText("tracing.not.supported"));
} else if (args[i].equals("-version")) {
if((i+1) >= args.length){
Util.version();
}
} else if (args[i].equals("-jni")) {
if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-force")) {
if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-Xnew")) {
// we're already using the new javah
} else if (args[i].equals("-old")) {
System.err.println(Util.getText("old.not.supported"));
Util.usage(1);
} else if (args[i].equals("-Xllni")) {
if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-llni")) {
if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-llniDouble")) {
if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-classpath")) {
i++;
if(i >= args.length){
Util.usage(1);
}else if(args[i].charAt(0) == '-') {
Util.error("no.classpath.specified");
}else if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].equals("-bootclasspath")) {
i++;
if(i >= args.length){
Util.usage(1);
}else if(args[i].charAt(0) == '-'){
Util.error("no.bootclasspath.specified");
}else if((i+1) >= args.length){
Util.error("no.classes.specified");
}
} else if (args[i].charAt(0) == '-') {
Util.error("unknown.option", args[i], null, true);
} else {
//break; /* The rest must be classes. */
}
}
/* Invoke javadoc */
String[] javadocargs = new String[args.length + 2];
int i = 0;
for(; i < args.length; i++) {
javadocargs[i] = args[i];
}
javadocargs[i] = "-private";
i++;
javadocargs[i] = "-Xclasses";
int rc = com.sun.tools.javadoc.Main.execute("javadoc", "com.sun.tools.javah.MainDoclet", javadocargs);
public static void main(String[] args) {
JavahTask t = new JavahTask();
int rc = t.run(args);
System.exit(rc);
}
/**
* Entry point that does <i>not</i> call System.exit.
* @param args command line arguments
* @param out output stream
* @return an exit code. 0 means success, non-zero means an error occurred.
*/
public static int run(String[] args, PrintWriter out) {
JavahTask t = new JavahTask();
t.setLog(out);
return t.run(args);
}
}

View file

@ -1,218 +0,0 @@
/*
* Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.javah;
import com.sun.javadoc.*;
import java.io.*;
/**
* A doclet to parse and execute commandline options.
*
* @author Sucheta Dambalkar(using code from old javap)
*/
public class MainDoclet{
public static String odir = null;
public static String ofile = null;
public static boolean stubs = false;
public static boolean jni = false;
public static boolean llni = false;
public static boolean doubleAlign = false;
public static boolean force = false;
public static String genclass = null;
/**
* Entry point.
*/
public static boolean start(RootDoc root) {
int j = 0;
int k = 0;
/**
* Command line options.
*/
String [][] cmdoptions = root.options();
/**
* Classes specified on command line.
*/
ClassDoc[] classes = root.classes();
/**
* Generator used by javah. Default is JNI.
*/
Gen g = new JNI(root);
validateOptions(cmdoptions);
/*
* Select native interface.
*/
if (jni && llni) Util.error("jni.llni.mixed");
if (llni)
g = new LLNI(doubleAlign, root);
if (g instanceof JNI && stubs) Util.error("jni.no.stubs");
/*
* Arrange for output destination.
*/
if (odir != null && ofile != null)
Util.error("dir.file.mixed");
if (odir != null)
g.setOutDir(odir);
if (ofile != null)
g.setOutFile(ofile);
/*
* Force set to false will turn off smarts about checking file
* content before writing.
*/
g.setForce(force);
/*
* Grab the rest of argv[] ... this must be the classes.
*/
if (classes.length == 0){
Util.error("no.classes.specified");
}
/*
* Set classes.
*/
g.setClasses(classes);
try {
g.run();
} catch (ClassNotFoundException cnfe) {
Util.error("class.not.found", cnfe.getMessage());
} catch (IOException ioe) {
Util.error("io.exception", ioe.getMessage());
}
return true;
}
/**
* Required doclet method.
*/
public static int optionLength(String option) {
if (option.equals("-o")) {
return 2;
} else if(option.equals("-d")){
return 2;
} else if (option.equals("-td")) {
return 1;
} else if (option.equals("-stubs")) {
return 1;
} else if(option.equals("-help")){
return 1;
} else if(option.equals("--help")){
return 1;
} else if(option.equals("-?")){
return 1;
} else if(option.equals("-h")){
return 1;
} else if(option.equals("-trace")){
return 1;
} else if(option.equals("-version")) {
return 1;
} else if(option.equals("-jni")){
return 1;
} else if(option.equals("-force")){
return 1;
} else if(option.equals("-Xllni")){
return 1;
} else if(option.equals("-llni")){
return 1;
} else if(option.equals("-llniDouble")){
return 1;
} else return 0;
}
/**
* Parse the command line options.
*/
public static void validateOptions(String cmdoptions[][]) {
/* Default values for options, overridden by user options. */
String bootcp = System.getProperty("sun.boot.class.path");
String usercp = System.getProperty("env.class.path");
for(int p = 0; p < cmdoptions.length; p++){
if (cmdoptions[p][0].equals("-o")) {
ofile = cmdoptions[p][1];
} else if(cmdoptions[p][0].equals("-d")){
odir = cmdoptions[p][1];
} else if (cmdoptions[p][0].equals("-td")) {
if (p ==cmdoptions.length)
Util.usage(1);
} else if (cmdoptions[p][0].equals("-stubs")) {
stubs = true;
} else if (cmdoptions[p][0].equals("-verbose")) {
Util.verbose = true;
} else if((cmdoptions[p][0].equals("-help"))
|| (cmdoptions[p][0].equals("--help"))
|| (cmdoptions[p][0].equals("-?"))
|| (cmdoptions[p][0].equals("-h"))) {
Util.usage(0);
} else if (cmdoptions[p][0].equals("-trace")) {
System.err.println(Util.getText("tracing.not.supported"));
} else if (cmdoptions[p][0].equals("-version")) {
Util.version();
} else if (cmdoptions[p][0].equals("-jni")) {
jni = true;
} else if (cmdoptions[p][0].equals("-force")) {
force = true;
} else if (cmdoptions[p][0].equals("-Xllni")) {
llni = true;
} else if (cmdoptions[p][0].equals("-llni")) {
llni = true;
} else if (cmdoptions[p][0].equals("-llniDouble")) {
llni = true; doubleAlign = true;
} else if (cmdoptions[p][0].equals("-classpath")) {
usercp = cmdoptions[p][1];
} else if (cmdoptions[p][0].equals("-bootclasspath")) {
bootcp = cmdoptions[p][1];
} else if((cmdoptions[p][0].charAt(0) == '-')
&& (!cmdoptions[p][0].equals("-private"))){
Util.error("unknown.option", cmdoptions[p][0], null, true);
} else {
break; /* The rest must be classes. */
}
}
if (Util.verbose) {
System.err.println("[ Search Path: "
+ bootcp
+ System.getProperty("file.separator")
+ usercp + " ]");
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,19 +26,27 @@
package com.sun.tools.javah;
import com.sun.javadoc.*;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
/**
* A utility for mangling java identifiers into C names. Should make
* this more fine grained and distribute the functionality to the
* generators.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Sucheta Dambalkar(Revised)
*/
class Mangle {
public class Mangle {
public static class Type {
public static final int CLASS = 1;
public static final int FIELDSTUB = 2;
public static final int FIELD = 3;
@ -49,8 +57,15 @@ class Mangle {
public static final int METHOD_JNI_LONG = 8;
};
private Elements elems;
private Types types;
public static final String mangle(String name, int mtype) {
Mangle(Elements elems, Types types) {
this.elems = elems;
this.types = types;
}
public final String mangle(CharSequence name, int mtype) {
StringBuffer result = new StringBuffer(100);
int length = name.length();
@ -98,15 +113,15 @@ class Mangle {
return result.toString();
}
public static String mangleMethod(MethodDoc method, RootDoc root, ClassDoc clazz,
public String mangleMethod(ExecutableElement method, TypeElement clazz,
int mtype) {
StringBuffer result = new StringBuffer(100);
result.append("Java_");
if (mtype == Mangle.Type.METHOD_JDK_1) {
result.append(mangle(clazz.qualifiedName(), Mangle.Type.CLASS));
result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS));
result.append('_');
result.append(mangle(method.name(),
result.append(mangle(method.getSimpleName(),
Mangle.Type.FIELD));
result.append("_stub");
return result.toString();
@ -115,13 +130,13 @@ class Mangle {
/* JNI */
result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
result.append('_');
result.append(mangle(method.name(),
result.append(mangle(method.getSimpleName(),
Mangle.Type.JNI));
if (mtype == Mangle.Type.METHOD_JNI_LONG) {
result.append("__");
String typesig = method.signature();
TypeSignature newTypeSig = new TypeSignature(root);
String sig = newTypeSig.getTypeSignature(typesig, method.returnType());
String typesig = signature(method);
TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(typesig, method.getReturnType());
sig = sig.substring(1);
sig = sig.substring(0, sig.lastIndexOf(')'));
sig = sig.replace('/', '.');
@ -131,15 +146,11 @@ class Mangle {
return result.toString();
}
//where
private static String getInnerQualifiedName(ClassDoc clazz) {
ClassDoc encl = clazz.containingClass();
if (encl == null)
return clazz.qualifiedName();
else
return getInnerQualifiedName(encl) + '$' + clazz.simpleTypeName();
private String getInnerQualifiedName(TypeElement clazz) {
return elems.getBinaryName(clazz).toString();
}
public static final String mangleChar(char ch) {
public final String mangleChar(char ch) {
String s = Integer.toHexString(ch);
int nzeros = 5 - s.length();
char[] result = new char[6];
@ -151,6 +162,19 @@ class Mangle {
return new String(result);
}
// Warning: duplicated in Gen
private String signature(ExecutableElement e) {
StringBuffer sb = new StringBuffer();
String sep = "(";
for (VariableElement p: e.getParameters()) {
sb.append(sep);
sb.append(types.erasure(p.asType()).toString());
sep = ",";
}
sb.append(")");
return sb.toString();
}
/* Warning: Intentional ASCII operation. */
private static final boolean isalnum(char ch) {
return ch <= 0x7f && /* quick test */

View file

@ -0,0 +1,147 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.javah; //javax.tools;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.concurrent.Callable;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.OptionChecker;
import javax.tools.StandardJavaFileManager;
import javax.tools.Tool;
/**
* This class is intended to be put in javax.tools.
*
* @see DiagnosticListener
* @see Diagnostic
* @see JavaFileManager
* @since 1.7
*
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
* you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public interface NativeHeaderTool extends Tool, OptionChecker {
/**
* Creates a future for a native header task with the given
* components and arguments. The task might not have
* completed as described in the NativeHeaderTask interface.
*
* <p>If a file manager is provided, it must be able to handle all
* locations defined in {@link StandardLocation}.
*
* @param out a Writer for additional output from the task;
* use {@code System.err} if {@code null}
* @param fileManager a file manager; if {@code null} use the
* task's standard filemanager
* @param diagnosticListener a diagnostic listener; if {@code
* null} use the compiler's default method for reporting
* diagnostics
* @param options task options, {@code null} means no options
* @param classes class names for which native headers should be generated
* @return an object representing the task to be done
* @throws RuntimeException if an unrecoverable error
* occurred in a user supplied component. The
* {@linkplain Throwable#getCause() cause} will be the error in
* user code.
* @throws IllegalArgumentException if any of the given
* compilation units are of other kind than
* {@linkplain JavaFileObject.Kind#SOURCE source}
*/
NativeHeaderTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes);
/**
* Gets a new instance of the standard file manager implementation
* for this tool. The file manager will use the given diagnostic
* listener for producing any non-fatal diagnostics. Fatal errors
* will be signalled with the appropriate exceptions.
*
* <p>The standard file manager will be automatically reopened if
* it is accessed after calls to {@code flush} or {@code close}.
* The standard file manager must be usable with other tools.
*
* @param diagnosticListener a diagnostic listener for non-fatal
* diagnostics; if {@code null} use the tool's default method
* for reporting diagnostics
* @param locale the locale to apply when formatting diagnostics;
* {@code null} means the {@linkplain Locale#getDefault() default locale}.
* @param charset the character set used for decoding bytes; if
* {@code null} use the platform default
* @return the standard file manager
*/
StandardJavaFileManager getStandardFileManager(
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Locale locale,
Charset charset);
/**
* Interface representing a future for a native header task. The
* task has not yet started. To start the task, call
* the {@linkplain #call call} method.
*
* <p>Before calling the call method, additional aspects of the
* task can be configured, for example, by calling the
* {@linkplain #setLocale setLocale} method.
*/
interface NativeHeaderTask extends Callable<Boolean> {
/**
* Set the locale to be applied when formatting diagnostics and
* other localized data.
*
* @param locale the locale to apply; {@code null} means apply no
* locale
* @throws IllegalStateException if the task has started
*/
void setLocale(Locale locale);
/**
* Performs this native header task. The task may only
* be performed once. Subsequent calls to this method throw
* IllegalStateException.
*
* @return true if and only all the files were processed without errors;
* false otherwise
*
* @throws RuntimeException if an unrecoverable error occurred
* in a user-supplied component. The
* {@linkplain Throwable#getCause() cause} will be the error
* in user code.
* @throws IllegalStateException if called more than once
*/
Boolean call();
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,19 +26,34 @@
package com.sun.tools.javah;
import com.sun.javadoc.*;
import java.io.*;
import java.util.*;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleTypeVisitor6;
/**
* Returns internal type signature.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*
* @author Sucheta Dambalkar
*/
public class TypeSignature{
RootDoc root = null;
Elements elems;
/* Signature Characters */
@ -56,8 +71,8 @@ public class TypeSignature{
public TypeSignature(RootDoc root){
this.root = root;
public TypeSignature(Elements elems){
this.elems = elems;
}
/*
@ -70,16 +85,15 @@ public class TypeSignature{
/*
* Returns the type signature of a method according to JVM specs
*/
public String getTypeSignature(String javasignature, Type returnType){
public String getTypeSignature(String javasignature, TypeMirror returnType){
String signature = null; //Java type signature.
String typeSignature = null; //Internal type signature.
Vector<Object> params = new Vector<Object>(); //List of parameters.
List<String> params = new ArrayList<String>(); //List of parameters.
String paramsig = null; //Java parameter signature.
String paramJVMSig = null; //Internal parameter signature.
String returnSig = null; //Java return type signature.
String returnJVMType = null; //Internal return type signature.
String dimension = null; //Array dimension.
int dimensions = 0; //Array dimension.
int startIndex = -1;
int endIndex = -1;
@ -87,28 +101,27 @@ public class TypeSignature{
int i = 0;
// Gets the actual java signature without parentheses.
if(javasignature != null){
if (javasignature != null) {
startIndex = javasignature.indexOf("(");
endIndex = javasignature.indexOf(")");
}
if(((startIndex != -1) && (endIndex != -1))
if (((startIndex != -1) && (endIndex != -1))
&&(startIndex+1 < javasignature.length())
&&(endIndex < javasignature.length())) {
signature = javasignature.substring(startIndex+1, endIndex);
}
// Separates parameters.
if(signature != null){
if(signature.indexOf(",") != -1){
if (signature != null) {
if (signature.indexOf(",") != -1) {
st = new StringTokenizer(signature, ",");
if(st != null){
if (st != null) {
while (st.hasMoreTokens()) {
params.add(st.nextToken());
}
}
}else {
} else {
params.add(signature);
}
}
@ -117,10 +130,10 @@ public class TypeSignature{
typeSignature = "(";
// Gets indivisual internal parameter signature.
while(params.isEmpty() != true){
paramsig =((String)params.remove(i)).trim();
while (params.isEmpty() != true) {
paramsig = params.remove(i).trim();
paramJVMSig = getParamJVMSignature(paramsig);
if(paramJVMSig != null){
if (paramJVMSig != null) {
typeSignature += paramJVMSig;
}
}
@ -130,36 +143,30 @@ public class TypeSignature{
// Get internal return type signature.
returnJVMType = "";
if(returnType != null){
dimension = returnType.dimension();
if (returnType != null) {
dimensions = dimensions(returnType);
}
if(dimension != null){
//Gets array dimension of return type.
while(dimension.indexOf("[]") != -1){
while (dimensions-- > 0) {
returnJVMType += "[";
int stindex = dimension.indexOf("]") + 1;
if(stindex <= dimension.length()){
dimension = dimension.substring(stindex);
}else dimension = "";
}
}
if(returnType != null){
returnSig = returnType.qualifiedTypeName();
if (returnType != null) {
returnSig = qualifiedTypeName(returnType);
returnJVMType += getComponentType(returnSig);
}else {
} else {
System.out.println("Invalid return type.");
}
typeSignature += returnJVMType;
return typeSignature;
}
/*
* Returns internal signature of a parameter.
*/
private String getParamJVMSignature(String paramsig){
private String getParamJVMSignature(String paramsig) {
String paramJVMSig = "";
String componentType ="";
@ -206,12 +213,13 @@ public class TypeSignature{
else if(componentType.equals("double")) JVMSig += SIG_DOUBLE ;
else {
if(!componentType.equals("")){
ClassDoc classNameDoc = root.classNamed(componentType);
TypeElement classNameDoc = elems.getTypeElement(componentType);
if(classNameDoc == null){
System.out.println("Invalid class type");
System.out.println("Invalid class type for " + componentType);
new Exception().printStackTrace();
}else {
String classname = classNameDoc.qualifiedName();
String classname = classNameDoc.getQualifiedName().toString();
String newclassname = classname.replace('.', '/');
JVMSig += "L";
JVMSig += newclassname;
@ -222,4 +230,43 @@ public class TypeSignature{
}
return JVMSig;
}
int dimensions(TypeMirror t) {
if (t.getKind() != TypeKind.ARRAY)
return 0;
return 1 + dimensions(((ArrayType) t).getComponentType());
}
String qualifiedTypeName(TypeMirror type) {
TypeVisitor<Name, Void> v = new SimpleTypeVisitor6<Name, Void>() {
@Override
public Name visitArray(ArrayType t, Void p) {
return t.getComponentType().accept(this, p);
}
@Override
public Name visitDeclared(DeclaredType t, Void p) {
return ((TypeElement) t.asElement()).getQualifiedName();
}
@Override
public Name visitPrimitive(PrimitiveType t, Void p) {
return elems.getName(t.toString());
}
@Override
public Name visitNoType(NoType t, Void p) {
if (t.getKind() == TypeKind.VOID)
return elems.getName("void");
return defaultAction(t, p);
}
@Override
public Name visitTypeVariable(TypeVariable t, Void p) {
return t.getUpperBound().accept(this, p);
}
};
return v.visit(type).toString();
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,12 +26,15 @@
package com.sun.tools.javah;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ResourceBundle;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
/**
* Messages, verbose and error handling support.
@ -41,42 +44,70 @@ import java.util.MissingResourceException;
* bug -- Bug has occurred in javah
* fatal -- We can't even find resources, so bail fast, don't localize
*
* <p><b>This is NOT part of any API supported by Sun Microsystems.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class Util {
/** Exit is used to replace the use of System.exit in the original javah.
*/
public static class Exit extends Error {
private static final long serialVersionUID = 430820978114067221L;
Exit(int exitValue) {
this(exitValue, null);
}
Exit(int exitValue, Throwable cause) {
super(cause);
this.exitValue = exitValue;
this.cause = cause;
}
Exit(Exit e) {
this(e.exitValue, e.cause);
}
public final int exitValue;
public final Throwable cause;
}
/*
* Help for verbosity.
*/
public static boolean verbose = false;
public boolean verbose = false;
public static void log(String s) {
System.out.println(s);
public PrintWriter log;
public DiagnosticListener<? super JavaFileObject> dl;
Util(PrintWriter log, DiagnosticListener<? super JavaFileObject> dl) {
this.log = log;
this.dl = dl;
}
public void log(String s) {
log.println(s);
}
/*
* Help for loading localized messages.
*/
private static ResourceBundle m;
private ResourceBundle m;
private static void initMessages() {
private void initMessages() throws Exit {
try {
m=ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n");
m = ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n");
} catch (MissingResourceException mre) {
fatal("Error loading resources. Please file a bug report.", mre);
}
}
public static String getText(String key) {
return getText(key, null, null);
}
private static String getText(String key, String a1, String a2){
private String getText(String key, Object... args) throws Exit {
if (m == null)
initMessages();
try {
return MessageFormat.format(m.getString(key),
new Object[] { a1, a2 });
return MessageFormat.format(m.getString(key), args);
} catch (MissingResourceException e) {
fatal("Key " + key + " not found in resources.", e);
}
@ -86,107 +117,74 @@ public class Util {
/*
* Usage message.
*/
public static void usage(int exitValue) {
if (exitValue == 0) {
System.out.println(getText("usage"));
} else {
System.err.println(getText("usage"));
}
System.exit(exitValue);
public void usage() throws Exit {
log.println(getText("usage"));
}
public static void version() {
System.out.println(getText("javah.version",
public void version() throws Exit {
log.println(getText("javah.version",
System.getProperty("java.version"), null));
System.exit(0);
}
/*
* Failure modes.
*/
public static void bug(String key) {
public void bug(String key) throws Exit {
bug(key, null);
}
public static void bug(String key, Exception e) {
if (e != null)
e.printStackTrace();
System.err.println(getText(key));
System.err.println(getText("bug.report"));
System.exit(11);
public void bug(String key, Exception e) throws Exit {
dl.report(createDiagnostic(Diagnostic.Kind.ERROR, key));
dl.report(createDiagnostic(Diagnostic.Kind.NOTE, "bug.report"));
throw new Exit(11, e);
}
public static void error(String key) {
error(key, null);
public void error(String key, Object... args) throws Exit {
dl.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));
throw new Exit(15);
}
public static void error(String key, String a1) {
error(key, a1, null);
}
public static void error(String key, String a1, String a2) {
error(key, a1, a2, false);
}
public static void error(String key, String a1, String a2,
boolean showUsage) {
System.err.println("Error: " + getText(key, a1, a2));
if (showUsage)
usage(15);
System.exit(15);
}
private static void fatal(String msg) {
private void fatal(String msg) throws Exit {
fatal(msg, null);
}
private static void fatal(String msg, Exception e) {
if (e != null) {
e.printStackTrace();
}
System.err.println(msg);
System.exit(10);
private void fatal(String msg, Exception e) throws Exit {
dl.report(createDiagnostic(Diagnostic.Kind.ERROR, "", msg));
throw new Exit(10, e);
}
/*
* Support for platform specific things in javah, such as pragma
* directives, exported symbols etc.
*/
static private ResourceBundle platform = null;
/*
* Set when platform has been initialized.
*/
static private boolean platformInit = false;
static String getPlatformString(String key) {
if (!platformInit) {
initPlatform();
platformInit = true;
private Diagnostic<JavaFileObject> createDiagnostic(
final Diagnostic.Kind kind, final String code, final Object... args) {
return new Diagnostic<JavaFileObject>() {
public String getCode() {
return code;
}
if (platform == null)
return null;
try {
return platform.getString(key);
} catch (MissingResourceException mre) {
public long getColumnNumber() {
return Diagnostic.NOPOS;
}
public long getEndPosition() {
return Diagnostic.NOPOS;
}
public Kind getKind() {
return kind;
}
public long getLineNumber() {
return Diagnostic.NOPOS;
}
public String getMessage(Locale locale) {
if (code.length() == 0)
return (String) args[0];
return getText(code, args); // FIXME locale
}
public long getPosition() {
return Diagnostic.NOPOS;
}
public JavaFileObject getSource() {
return null;
}
public long getStartPosition() {
return Diagnostic.NOPOS;
}
private static void initPlatform() {
String os = System.getProperty("os.name");
if (os.startsWith("Windows")) {
os = "win32";
} else if (os.indexOf("Linux") >= 0) {
os = "Linux";
}
String arch = System.getProperty("os.arch");
String resname = "com.sun.tools.javah.resources." + os + "_" + arch;
try {
platform=ResourceBundle.getBundle(resname);
} catch (MissingResourceException mre) {
// fatal("Error loading resources. Please file a bug report.", mre);
}
};
}
}

View file

@ -1,27 +0,0 @@
#
# Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
pack.pragma.start=\#pragma pack(4)\n
pack.pragma.end=\#pragma pack()\n

View file

@ -1,27 +0,0 @@
#
# Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
pack.pragma.start=\#pragma pack(4)\n
pack.pragma.end=\#pragma pack()\n

View file

@ -1,27 +0,0 @@
#
# Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
pack.pragma.start=\#pragma pack(4)\n
pack.pragma.end=\#pragma pack()\n

View file

@ -84,6 +84,32 @@ where [options] include:\n\
<classes> are specified with their fully qualified names (for\n\
instance, java.lang.Object).\n
main.usage=\
Usage: \n\
\ javah [options] <classes>\n\
where [options] include:
main.opt.o=\
\ -o <file> Output file (only one of -d or -o may be used)
main.opt.d=\
\ -d <dir> Output directory
main.opt.v=\
\ -v -verbose Enable verbose output
main.opt.help=\
\ -h --help -? Print this message
main.opt.version=\
\ -version Print version information
main.opt.jni=\
\ -jni Generate JNI-style header file (default)
main.opt.force=\
\ -force Always write output files
main.opt.classpath=\
\ -classpath <path> Path from which to load classes
main.opt.bootclasspath=\
\ -bootclasspath <path> Path from which to load bootstrap classes
main.usage.foot=\
<classes> are specified with their fully qualified names\n\
(for example, java.lang.Object).
#
# Version string.
#
@ -116,3 +142,12 @@ unknown.type.for.field=\
An unknown type encountered when generating old style headers.
unknown.type.in.method.signature=\
An unknown type eccountered when generating old style stubs.
err.prefix=Error:
err.cant.use.option.for.fm=Can't use {0} option with given file manager
err.internal.error=Internal error: {0}
err.ioerror=IO error: {0}
err.missing.arg=value missing for {0}
err.no.classes.specified=no classes specified
err.unknown.option=unknown option: {0}

View file

@ -1,28 +0,0 @@
#
# Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
dll.export=__declspec(dllexport)
pack.pragma.start=\#pragma pack(4)\n
pack.pragma.end=\#pragma pack()\n

View file

@ -42,7 +42,7 @@ import javax.tools.Tool;
* @see DiagnosticListener
* @see Diagnostic
* @see JavaFileManager
* @since 1.6
* @since 1.7
*
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
* you write code that depends on this, you do so at your own risk.

View file

@ -0,0 +1,239 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6572945
* @summary rewrite javah as an annotation processor, instead of as a doclet
* @build TestClass1 TestClass2 TestClass3
* @run main T6572945
*/
import java.io.*;
import java.util.*;
import com.sun.tools.javah.Main;
public class T6572945
{
static File testSrc = new File(System.getProperty("test.src", "."));
static File testClasses = new File(System.getProperty("test.classes", "."));
static boolean isWindows = System.getProperty("os.name").startsWith("Windows");
public static void main(String... args)
throws IOException, InterruptedException
{
boolean ok = new T6572945().run(args);
if (!ok)
throw new Error("Test Failed");
}
public boolean run(String[] args)
throws IOException, InterruptedException
{
if (args.length == 1)
jdk = new File(args[0]);
test("-o", "jni.file.1", "-jni", "TestClass1");
test("-o", "jni.file.2", "-jni", "TestClass1", "TestClass2");
test("-d", "jni.dir.1", "-jni", "TestClass1", "TestClass2");
test("-o", "jni.file.3", "-jni", "TestClass3");
// The following tests are disabled because llni support has been
// discontinued, and because bugs in old javah means that character
// for character testing against output from old javah does not work.
// In fact, the LLNI impl in new javah is actually better than the
// impl in old javah because of a couple of significant bug fixes.
// test("-o", "llni.file.1", "-llni", "TestClass1");
// test("-o", "llni.file.2", "-llni", "TestClass1", "TestClass2");
// test("-d", "llni.dir.1", "-llni", "TestClass1", "TestClass2");
// test("-o", "llni.file.3", "-llni", "TestClass3");
return (errors == 0);
}
void test(String... args)
throws IOException, InterruptedException
{
String[] cp_args = new String[args.length + 2];
cp_args[0] = "-classpath";
cp_args[1] = testClasses.getPath();
System.arraycopy(args, 0, cp_args, 2, args.length);
if (jdk != null)
init(cp_args);
File out = null;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-o")) {
out = new File(args[++i]);
break;
} else if (args[i].equals("-d")) {
out = new File(args[++i]);
out.mkdirs();
break;
}
}
try {
System.out.println("test: " + Arrays.asList(cp_args));
// // Uncomment and use the following lines to execute javah via the
// // command line -- for example, to run old javah and set up the golden files
// List<String> cmd = new ArrayList<String>();
// File javaHome = new File(System.getProperty("java.home"));
// if (javaHome.getName().equals("jre"))
// javaHome = javaHome.getParentFile();
// File javah = new File(new File(javaHome, "bin"), "javah");
// cmd.add(javah.getPath());
// cmd.addAll(Arrays.asList(cp_args));
// ProcessBuilder pb = new ProcessBuilder(cmd);
// pb.redirectErrorStream(true);
// pb.start();
// Process p = pb.start();
// String line;
// BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
// while ((line = in.readLine()) != null)
// System.err.println(line);
// in.close();
// int rc = p.waitFor();
// Use new javah
PrintWriter err = new PrintWriter(System.err, true);
int rc = Main.run(cp_args, err);
if (rc != 0) {
error("javah failed: rc=" + rc);
return;
}
// The golden files use the LL suffix for long constants, which
// is used on Linux and Solaris. On Windows, the suffix is i64,
// so compare will update the golden files on the fly before the
// final comparison.
compare(new File(new File(testSrc, "gold"), out.getName()), out);
} catch (Throwable t) {
t.printStackTrace();
error("javah threw exception");
}
}
void init(String[] args) throws IOException, InterruptedException {
String[] cmdArgs = new String[args.length + 1];
cmdArgs[0] = new File(new File(jdk, "bin"), "javah").getPath();
System.arraycopy(args, 0, cmdArgs, 1, args.length);
System.out.println("init: " + Arrays.asList(cmdArgs));
ProcessBuilder pb = new ProcessBuilder(cmdArgs);
pb.directory(new File(testSrc, "gold"));
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = in.readLine()) != null)
System.out.println("javah: " + line);
int rc = p.waitFor();
if (rc != 0)
error("javah: exit code " + rc);
}
/** Compare two directories.
* @param f1 The golden directory
* @param f2 The directory to be compared
*/
void compare(File f1, File f2) {
compare(f1, f2, null);
}
/** Compare two files or directories
* @param f1 The golden directory
* @param f2 The directory to be compared
* @param p An optional path identifying a file within the two directories
*/
void compare(File f1, File f2, String p) {
File f1p = (p == null ? f1 : new File(f1, p));
File f2p = (p == null ? f2 : new File(f2, p));
System.out.println("compare " + f1p + " " + f2p);
if (f1p.isDirectory() && f2p.isDirectory()) {
Set<String> children = new HashSet<String>();
children.addAll(Arrays.asList(f1p.list()));
children.addAll(Arrays.asList(f2p.list()));
for (String c: children) {
compare(f1, f2, new File(p, c).getPath()); // null-safe for p
}
}
else if (f1p.isFile() && f2p.isFile()) {
String s1 = read(f1p);
if (isWindows) {
// f1/s1 is the golden file
// on Windows, long constants use the i64 suffix, not LL
s1 = s1.replaceAll("( [0-9]+)LL\n", "$1i64\n");
}
String s2 = read(f2p);
if (!s1.equals(s2)) {
System.out.println("File: " + f1p + "\n" + s1);
System.out.println("File: " + f2p + "\n" + s2);
error("Files differ: " + f1p + " " + f2p);
}
}
else if (f1p.exists() && !f2p.exists())
error("Only in " + f1 + ": " + p);
else if (f2p.exists() && !f1p.exists())
error("Only in " + f2 + ": " + p);
else
error("Files differ: " + f1p + " " + f2p);
}
private String read(File f) {
try {
BufferedReader in = new BufferedReader(new FileReader(f));
try {
StringBuilder sb = new StringBuilder((int) f.length());
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
return sb.toString();
} finally {
try {
in.close();
} catch (IOException e) {
}
}
} catch (IOException e) {
error("error reading " + f + ": " + e);
return "";
}
}
private void error(String msg) {
System.out.println(msg);
errors++;
}
private int errors;
private File jdk;
}

View file

@ -0,0 +1,475 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.util.List;
public class TestClass1 {
// simple types
byte b;
short s;
int i;
long l;
float f;
double d;
Object o;
String t;
List<String> g;
// constants
static final byte bc = 0;
static final short sc = 0;
static final int ic = 0;
static final long lc = 0;
static final float fc = 0;
static final double dc = 0;
static final Object oc = null;
static final String tc = "";
static final List<String> gc = null;
// simple arrays
byte[] ba;
short[] sa; // not handled corrected by javah v6
int[] ia;
long[] la;
float[] fa;
double[] da;
Object[] oa;
String[] ta;
List<String>[] ga;
// multidimensional arrays
byte[][] baa;
short[][] saa;
int[][] iaa;
long[][] laa;
float[][] faa;
double[][] daa;
Object[][] oaa;
String[][] taa;
List<String>[] gaa;
// simple Java methods
byte bm() { return 0; }
short sm() { return 0; }
int im() { return 0; }
long lm() { return 0; }
float fm() { return 0; }
double dm() { return 0; }
Object om() { return null; }
String tm() { return ""; }
List<String> gm() { return null; }
void vm() { }
byte[] bam() { return null; }
short[] sam() { return null; }
int[] iam() { return null; }
long[] lam() { return null; }
float[] fam() { return null; }
double[] dam() { return null; }
Object[] oam() { return null; }
String[] tam() { return null; }
List<String>[] gam() { return null; }
byte[][] baam() { return null; }
short[][] saam() { return null; }
int[][] iaam() { return null; }
long[][] laam() { return null; }
float[][] faam() { return null; }
double[][] daam() { return null; }
Object[][] oaam() { return null; }
String[][] taam() { return null; }
List<String>[] gaam() { return null; }
// simple native methods
native byte bmn();
native short smn();
native int imn();
native long lmn();
native float fmn();
native double dmn();
native Object omn();
native String tmn();
native List<String> gmn();
native void vmn();
native byte[] bamn();
native short[] samn();
native int[] iamn();
native long[] lamn();
native float[] famn();
native double[] damn();
native Object[] oamn();
native String[] tamn();
native List<String>[] gamn();
native byte[][] baamn();
native short[][] saamn();
native int[][] iaamn();
native long[][] laamn();
native float[][] faamn();
native double[][] daamn();
native Object[][] oaamn();
native String[][] taamn();
native List<String>[] gaamn();
// overloaded Java methods
byte bm1() { return 0; }
short sm1() { return 0; }
int im1() { return 0; }
long lm1() { return 0; }
float fm1() { return 0; }
double dm1() { return 0; }
Object om1() { return null; }
String tm1() { return ""; }
List<String> gm1() { return null; }
void vm1() { }
byte bm2(int i) { return 0; }
short sm2(int i) { return 0; }
int im2(int i) { return 0; }
long lm2(int i) { return 0; }
float fm2(int i) { return 0; }
double dm2(int i) { return 0; }
Object om2(int i) { return null; }
String tm2(int i) { return ""; }
List<String> gm2(int i) { return null; }
void vm2(int i) { }
// overloaded native methods
native byte bmn1();
native short smn1();
native int imn1();
native long lmn1();
native float fmn1();
native double dmn1();
native Object omn1();
native String tmn1();
native List<String> gmn1();
native void vmn1();
native byte bmn2(int i);
native short smn2(int i);
native int imn2(int i);
native long lmn2(int i);
native float fmn2(int i);
native double dmn2(int i);
native Object omn2(int i);
native String tmn2(int i);
native List<String> gmn2(int i);
native void vmn2(int i);
// arg types for Java methods
void mb(byte b) { }
void ms(short s) { }
void mi(int i) { }
void ml(long l) { }
void mf(float f) { }
void md(double d) { }
void mo(Object o) { }
void mt(String t) { }
void mg(List<String> g) { }
// arg types for native methods
native void mbn(byte b);
native void msn(short s);
native void min(int i);
native void mln(long l);
native void mfn(float f);
native void mdn(double d);
native void mon(Object o);
native void mtn(String t);
native void mgn(List<String> g);
static class Inner1 {
// simple types
byte b;
short s;
int i;
long l;
float f;
double d;
Object o;
String t;
List<String> g;
// constants
static final byte bc = 0;
static final short sc = 0;
static final int ic = 0;
static final long lc = 0;
static final float fc = 0;
static final double dc = 0;
static final Object oc = null;
static final String tc = "";
static final List<String> gc = null;
// simple arrays
byte[] ba;
// short[] sa; // not handled corrected by javah v6
int[] ia;
long[] la;
float[] fa;
double[] da;
Object[] oa;
String[] ta;
List<String>[] ga;
// multidimensional arrays
byte[][] baa;
short[][] saa;
int[][] iaa;
long[][] laa;
float[][] faa;
double[][] daa;
Object[][] oaa;
String[][] taa;
List<String>[] gaa;
// simple Java methods
byte bm() { return 0; }
short sm() { return 0; }
int im() { return 0; }
long lm() { return 0; }
float fm() { return 0; }
double dm() { return 0; }
Object om() { return null; }
String tm() { return ""; }
List<String> gm() { return null; }
void vm() { }
// simple native methods
native byte bmn();
native short smn();
native int imn();
native long lmn();
native float fmn();
native double dmn();
native Object omn();
native String tmn();
native List<String> gmn();
native void vmn();
// overloaded Java methods
byte bm1() { return 0; }
short sm1() { return 0; }
int im1() { return 0; }
long lm1() { return 0; }
float fm1() { return 0; }
double dm1() { return 0; }
Object om1() { return null; }
String tm1() { return ""; }
List<String> gm1() { return null; }
void vm1() { }
byte bm2(int i) { return 0; }
short sm2(int i) { return 0; }
int im2(int i) { return 0; }
long lm2(int i) { return 0; }
float fm2(int i) { return 0; }
double dm2(int i) { return 0; }
Object om2(int i) { return null; }
String tm2(int i) { return ""; }
List<String> gm2(int i) { return null; }
void vm2(int i) { }
// overloaded native methods
native byte bmn1();
native short smn1();
native int imn1();
native long lmn1();
native float fmn1();
native double dmn1();
native Object omn1();
native String tmn1();
native List<String> gmn1();
native void vmn1();
native byte bmn2(int i);
native short smn2(int i);
native int imn2(int i);
native long lmn2(int i);
native float fmn2(int i);
native double dmn2(int i);
native Object omn2(int i);
native String tmn2(int i);
native List<String> gmn2(int i);
native void vmn2(int i);
// arg types for Java methods
void mb(byte b) { }
void ms(short s) { }
void mi(int i) { }
void ml(long l) { }
void mf(float f) { }
void md(double d) { }
void mo(Object o) { }
void mt(String t) { }
void mg(List<String> g) { }
// arg types for native methods
native void mbn(byte b);
native void msn(short s);
native void min(int i);
native void mln(long l);
native void mfn(float f);
native void mdn(double d);
native void mon(Object o);
native void mtn(String t);
native void mgn(List<String> g);
}
class Inner2 {
// simple types
byte b;
short s;
int i;
long l;
float f;
double d;
Object o;
String t;
List<String> g;
// constants
static final byte bc = 0;
static final short sc = 0;
static final int ic = 0;
static final long lc = 0;
static final float fc = 0;
static final double dc = 0;
//static final Object oc = null;
static final String tc = "";
//static final List<String> gc = null;
// simple arrays
byte[] ba;
// short[] sa; // not handled corrected by javah v6
int[] ia;
long[] la;
float[] fa;
double[] da;
Object[] oa;
String[] ta;
List<String>[] ga;
// multidimensional arrays
byte[][] baa;
short[][] saa;
int[][] iaa;
long[][] laa;
float[][] faa;
double[][] daa;
Object[][] oaa;
String[][] taa;
List<String>[] gaa;
// simple Java methods
byte bm() { return 0; }
short sm() { return 0; }
int im() { return 0; }
long lm() { return 0; }
float fm() { return 0; }
double dm() { return 0; }
Object om() { return null; }
String tm() { return ""; }
List<String> gm() { return null; }
void vm() { }
// simple native methods
native byte bmn();
native short smn();
native int imn();
native long lmn();
native float fmn();
native double dmn();
native Object omn();
native String tmn();
native List<String> gmn();
native void vmn();
// overloaded Java methods
byte bm1() { return 0; }
short sm1() { return 0; }
int im1() { return 0; }
long lm1() { return 0; }
float fm1() { return 0; }
double dm1() { return 0; }
Object om1() { return null; }
String tm1() { return ""; }
List<String> gm1() { return null; }
void vm1() { }
byte bm2(int i) { return 0; }
short sm2(int i) { return 0; }
int im2(int i) { return 0; }
long lm2(int i) { return 0; }
float fm2(int i) { return 0; }
double dm2(int i) { return 0; }
Object om2(int i) { return null; }
String tm2(int i) { return ""; }
List<String> gm2(int i) { return null; }
void vm2(int i) { }
// overloaded native methods
native byte bmn1();
native short smn1();
native int imn1();
native long lmn1();
native float fmn1();
native double dmn1();
native Object omn1();
native String tmn1();
native List<String> gmn1();
native void vmn1();
native byte bmn2(int i);
native short smn2(int i);
native int imn2(int i);
native long lmn2(int i);
native float fmn2(int i);
native double dmn2(int i);
native Object omn2(int i);
native String tmn2(int i);
native List<String> gmn2(int i);
native void vmn2(int i);
// arg types for Java methods
void mb(byte b) { }
void ms(short s) { }
void mi(int i) { }
void ml(long l) { }
void mf(float f) { }
void md(double d) { }
void mo(Object o) { }
void mt(String t) { }
void mg(List<String> g) { }
// arg types for native methods
native void mbn(byte b);
native void msn(short s);
native void min(int i);
native void mln(long l);
native void mfn(float f);
native void mdn(double d);
native void mon(Object o);
native void mtn(String t);
native void mgn(List<String> g);
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
public class TestClass2 {
byte b;
short s;
int i;
long l;
float f;
double d;
Object o;
String t;
}

View file

@ -0,0 +1,51 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
public class TestClass3 {
public int tc3;
public class Inner1 {
public int tc3i1;
public class Inner1A {
public int tc3i1i1a;
}
public class Inner1B {
public int tc3i1i1b;
}
}
public class Inner2 {
public int tc321;
public class Inner2A {
public int tc3i2i2a;
}
public class Inner2B {
public int tc3i2i2b;
}
}
}

View file

@ -0,0 +1,481 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestClass1 */
#ifndef _Included_TestClass1
#define _Included_TestClass1
#ifdef __cplusplus
extern "C" {
#endif
#undef TestClass1_bc
#define TestClass1_bc 0L
#undef TestClass1_sc
#define TestClass1_sc 0L
#undef TestClass1_ic
#define TestClass1_ic 0L
#undef TestClass1_lc
#define TestClass1_lc 0LL
#undef TestClass1_fc
#define TestClass1_fc 0.0f
#undef TestClass1_dc
#define TestClass1_dc 0.0
/*
* Class: TestClass1
* Method: bmn
* Signature: ()B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_bmn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: smn
* Signature: ()S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_smn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: imn
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestClass1_imn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: lmn
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_lmn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: fmn
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_fmn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: dmn
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_dmn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: omn
* Signature: ()Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_omn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: tmn
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_tmn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: gmn
* Signature: ()Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_gmn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: vmn
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestClass1_vmn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: bamn
* Signature: ()[B
*/
JNIEXPORT jbyteArray JNICALL Java_TestClass1_bamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: samn
* Signature: ()[S
*/
JNIEXPORT jshortArray JNICALL Java_TestClass1_samn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: iamn
* Signature: ()[I
*/
JNIEXPORT jintArray JNICALL Java_TestClass1_iamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: lamn
* Signature: ()[J
*/
JNIEXPORT jlongArray JNICALL Java_TestClass1_lamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: famn
* Signature: ()[F
*/
JNIEXPORT jfloatArray JNICALL Java_TestClass1_famn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: damn
* Signature: ()[D
*/
JNIEXPORT jdoubleArray JNICALL Java_TestClass1_damn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: oamn
* Signature: ()[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_oamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: tamn
* Signature: ()[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_tamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: gamn
* Signature: ()[Ljava/util/List;
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_gamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: baamn
* Signature: ()[[B
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_baamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: saamn
* Signature: ()[[S
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_saamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: iaamn
* Signature: ()[[I
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_iaamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: laamn
* Signature: ()[[J
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_laamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: faamn
* Signature: ()[[F
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_faamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: daamn
* Signature: ()[[D
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_daamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: oaamn
* Signature: ()[[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_oaamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: taamn
* Signature: ()[[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_taamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: gaamn
* Signature: ()[Ljava/util/List;
*/
JNIEXPORT jobjectArray JNICALL Java_TestClass1_gaamn
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: bmn1
* Signature: ()B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_bmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: smn1
* Signature: ()S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_smn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: imn1
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestClass1_imn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: lmn1
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_lmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: fmn1
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_fmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: dmn1
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_dmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: omn1
* Signature: ()Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_omn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: tmn1
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_tmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: gmn1
* Signature: ()Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_gmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: vmn1
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestClass1_vmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1
* Method: bmn2
* Signature: (I)B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_bmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: smn2
* Signature: (I)S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_smn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: imn2
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_TestClass1_imn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: lmn2
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_lmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: fmn2
* Signature: (I)F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_fmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: dmn2
* Signature: (I)D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_dmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: omn2
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_omn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: tmn2
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_tmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: gmn2
* Signature: (I)Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_gmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: vmn2
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestClass1_vmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: mbn
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_TestClass1_mbn
(JNIEnv *, jobject, jbyte);
/*
* Class: TestClass1
* Method: msn
* Signature: (S)V
*/
JNIEXPORT void JNICALL Java_TestClass1_msn
(JNIEnv *, jobject, jshort);
/*
* Class: TestClass1
* Method: min
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestClass1_min
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1
* Method: mln
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_TestClass1_mln
(JNIEnv *, jobject, jlong);
/*
* Class: TestClass1
* Method: mfn
* Signature: (F)V
*/
JNIEXPORT void JNICALL Java_TestClass1_mfn
(JNIEnv *, jobject, jfloat);
/*
* Class: TestClass1
* Method: mdn
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_TestClass1_mdn
(JNIEnv *, jobject, jdouble);
/*
* Class: TestClass1
* Method: mon
* Signature: (Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_mon
(JNIEnv *, jobject, jobject);
/*
* Class: TestClass1
* Method: mtn
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_mtn
(JNIEnv *, jobject, jstring);
/*
* Class: TestClass1
* Method: mgn
* Signature: (Ljava/util/List;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_mgn
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,337 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestClass1_Inner1 */
#ifndef _Included_TestClass1_Inner1
#define _Included_TestClass1_Inner1
#ifdef __cplusplus
extern "C" {
#endif
#undef TestClass1_Inner1_bc
#define TestClass1_Inner1_bc 0L
#undef TestClass1_Inner1_sc
#define TestClass1_Inner1_sc 0L
#undef TestClass1_Inner1_ic
#define TestClass1_Inner1_ic 0L
#undef TestClass1_Inner1_lc
#define TestClass1_Inner1_lc 0LL
#undef TestClass1_Inner1_fc
#define TestClass1_Inner1_fc 0.0f
#undef TestClass1_Inner1_dc
#define TestClass1_Inner1_dc 0.0
/*
* Class: TestClass1_Inner1
* Method: bmn
* Signature: ()B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_00024Inner1_bmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: smn
* Signature: ()S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_00024Inner1_smn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: imn
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestClass1_00024Inner1_imn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: lmn
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_00024Inner1_lmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: fmn
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_00024Inner1_fmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: dmn
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_00024Inner1_dmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: omn
* Signature: ()Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner1_omn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: tmn
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_00024Inner1_tmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: gmn
* Signature: ()Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner1_gmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: vmn
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_vmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: bmn1
* Signature: ()B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_00024Inner1_bmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: smn1
* Signature: ()S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_00024Inner1_smn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: imn1
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestClass1_00024Inner1_imn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: lmn1
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_00024Inner1_lmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: fmn1
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_00024Inner1_fmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: dmn1
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_00024Inner1_dmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: omn1
* Signature: ()Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner1_omn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: tmn1
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_00024Inner1_tmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: gmn1
* Signature: ()Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner1_gmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: vmn1
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_vmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner1
* Method: bmn2
* Signature: (I)B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_00024Inner1_bmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: smn2
* Signature: (I)S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_00024Inner1_smn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: imn2
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_TestClass1_00024Inner1_imn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: lmn2
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_00024Inner1_lmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: fmn2
* Signature: (I)F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_00024Inner1_fmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: dmn2
* Signature: (I)D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_00024Inner1_dmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: omn2
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner1_omn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: tmn2
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_00024Inner1_tmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: gmn2
* Signature: (I)Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner1_gmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: vmn2
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_vmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: mbn
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_mbn
(JNIEnv *, jobject, jbyte);
/*
* Class: TestClass1_Inner1
* Method: msn
* Signature: (S)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_msn
(JNIEnv *, jobject, jshort);
/*
* Class: TestClass1_Inner1
* Method: min
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_min
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner1
* Method: mln
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_mln
(JNIEnv *, jobject, jlong);
/*
* Class: TestClass1_Inner1
* Method: mfn
* Signature: (F)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_mfn
(JNIEnv *, jobject, jfloat);
/*
* Class: TestClass1_Inner1
* Method: mdn
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_mdn
(JNIEnv *, jobject, jdouble);
/*
* Class: TestClass1_Inner1
* Method: mon
* Signature: (Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_mon
(JNIEnv *, jobject, jobject);
/*
* Class: TestClass1_Inner1
* Method: mtn
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_mtn
(JNIEnv *, jobject, jstring);
/*
* Class: TestClass1_Inner1
* Method: mgn
* Signature: (Ljava/util/List;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner1_mgn
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,337 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestClass1_Inner2 */
#ifndef _Included_TestClass1_Inner2
#define _Included_TestClass1_Inner2
#ifdef __cplusplus
extern "C" {
#endif
#undef TestClass1_Inner2_bc
#define TestClass1_Inner2_bc 0L
#undef TestClass1_Inner2_sc
#define TestClass1_Inner2_sc 0L
#undef TestClass1_Inner2_ic
#define TestClass1_Inner2_ic 0L
#undef TestClass1_Inner2_lc
#define TestClass1_Inner2_lc 0LL
#undef TestClass1_Inner2_fc
#define TestClass1_Inner2_fc 0.0f
#undef TestClass1_Inner2_dc
#define TestClass1_Inner2_dc 0.0
/*
* Class: TestClass1_Inner2
* Method: bmn
* Signature: ()B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_00024Inner2_bmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: smn
* Signature: ()S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_00024Inner2_smn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: imn
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestClass1_00024Inner2_imn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: lmn
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_00024Inner2_lmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: fmn
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_00024Inner2_fmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: dmn
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_00024Inner2_dmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: omn
* Signature: ()Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner2_omn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: tmn
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_00024Inner2_tmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: gmn
* Signature: ()Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner2_gmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: vmn
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_vmn
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: bmn1
* Signature: ()B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_00024Inner2_bmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: smn1
* Signature: ()S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_00024Inner2_smn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: imn1
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestClass1_00024Inner2_imn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: lmn1
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_00024Inner2_lmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: fmn1
* Signature: ()F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_00024Inner2_fmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: dmn1
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_00024Inner2_dmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: omn1
* Signature: ()Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner2_omn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: tmn1
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_00024Inner2_tmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: gmn1
* Signature: ()Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner2_gmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: vmn1
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_vmn1
(JNIEnv *, jobject);
/*
* Class: TestClass1_Inner2
* Method: bmn2
* Signature: (I)B
*/
JNIEXPORT jbyte JNICALL Java_TestClass1_00024Inner2_bmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: smn2
* Signature: (I)S
*/
JNIEXPORT jshort JNICALL Java_TestClass1_00024Inner2_smn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: imn2
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_TestClass1_00024Inner2_imn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: lmn2
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_TestClass1_00024Inner2_lmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: fmn2
* Signature: (I)F
*/
JNIEXPORT jfloat JNICALL Java_TestClass1_00024Inner2_fmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: dmn2
* Signature: (I)D
*/
JNIEXPORT jdouble JNICALL Java_TestClass1_00024Inner2_dmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: omn2
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner2_omn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: tmn2
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_TestClass1_00024Inner2_tmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: gmn2
* Signature: (I)Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_TestClass1_00024Inner2_gmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: vmn2
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_vmn2
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: mbn
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_mbn
(JNIEnv *, jobject, jbyte);
/*
* Class: TestClass1_Inner2
* Method: msn
* Signature: (S)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_msn
(JNIEnv *, jobject, jshort);
/*
* Class: TestClass1_Inner2
* Method: min
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_min
(JNIEnv *, jobject, jint);
/*
* Class: TestClass1_Inner2
* Method: mln
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_mln
(JNIEnv *, jobject, jlong);
/*
* Class: TestClass1_Inner2
* Method: mfn
* Signature: (F)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_mfn
(JNIEnv *, jobject, jfloat);
/*
* Class: TestClass1_Inner2
* Method: mdn
* Signature: (D)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_mdn
(JNIEnv *, jobject, jdouble);
/*
* Class: TestClass1_Inner2
* Method: mon
* Signature: (Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_mon
(JNIEnv *, jobject, jobject);
/*
* Class: TestClass1_Inner2
* Method: mtn
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_mtn
(JNIEnv *, jobject, jstring);
/*
* Class: TestClass1_Inner2
* Method: mgn
* Signature: (Ljava/util/List;)V
*/
JNIEXPORT void JNICALL Java_TestClass1_00024Inner2_mgn
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,13 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestClass2 */
#ifndef _Included_TestClass2
#define _Included_TestClass2
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,79 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestClass3 */
#ifndef _Included_TestClass3
#define _Included_TestClass3
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
/* Header for class TestClass3_Inner2 */
#ifndef _Included_TestClass3_Inner2
#define _Included_TestClass3_Inner2
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
/* Header for class TestClass3_Inner2_Inner2B */
#ifndef _Included_TestClass3_Inner2_Inner2B
#define _Included_TestClass3_Inner2_Inner2B
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
/* Header for class TestClass3_Inner2_Inner2A */
#ifndef _Included_TestClass3_Inner2_Inner2A
#define _Included_TestClass3_Inner2_Inner2A
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
/* Header for class TestClass3_Inner1 */
#ifndef _Included_TestClass3_Inner1
#define _Included_TestClass3_Inner1
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
/* Header for class TestClass3_Inner1_Inner1B */
#ifndef _Included_TestClass3_Inner1_Inner1B
#define _Included_TestClass3_Inner1_Inner1B
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
/* Header for class TestClass3_Inner1_Inner1A */
#ifndef _Included_TestClass3_Inner1_Inner1A
#define _Included_TestClass3_Inner1_Inner1A
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -77,10 +77,7 @@ GENERATED_HEADER_FILE=ParamClassTest.h
rm -f ParamClassTest.class MissingParamClassException.class ParamClassTest.h
rm -f ${TMP1}
cp ${TESTSRC}${FS}ParamClassTest.java .
cp ${TESTSRC}${FS}MissingParamClassException.java .
"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java"
"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java" "${TESTSRC}${FS}MissingParamClassException.java"
# Before running javah remove dependent class file
rm -f MissingParamClassException.class
@ -88,15 +85,12 @@ rm -f MissingParamClassException.class
"${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1}
if [ -f $GENERATED_HEADER_FILE ]; then
echo "Failed"
exit 1
echo "1-- Failed: $GENERATED_HEADER_FILE found"
rc=1
fi
if [ ! -f ${TMP1} ]; then
echo "Failed"
exit 1
else
echo "Passed"
exit 0
if [ ! -s ${TMP1} ]; then
echo "1-- Failed: ${TMP1} is empty"
rc=1
fi
# Clean out work dir
@ -104,7 +98,9 @@ rm -f MissingParamClassException.class ParamClassTest.class
rm -f $GENERATED_HEADER_FILE $TMP1
# Re-compile everything
"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . ${TESTSRC}${FS}ParamClassTest.java
"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java" "${TESTSRC}${FS}MissingParamClassException.java"
# Before re-run of javah remove dependent class file Param.class
rm -f Param.class
@ -112,13 +108,17 @@ rm -f Param.class
"${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1}
if [ -f $GENERATED_HEADER_FILE ]; then
echo "Failed"
exit 1
echo "2-- Failed: $GENERATED_HEADER_FILE found"
rc=1
fi
if [ ! -f ${TMP1} ]; then
echo "Failed"
exit 1
if [ ! -s ${TMP1} ]; then
echo "2-- Failed: ${TMP1} is empty"
rc=1
fi
if [ "$rc" = "" ]; then
echo Passed
else
echo "Passed"
exit 0
echo Failed
exit 1
fi

View file

@ -0,0 +1,265 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.sun.tools.classfile.AccessFlags;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Method;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.LinkedHashSet;
public class CompareTest {
String[][] testCases = {
{ },
{ "-jni" },
// { "-llni" },
};
public static void main(String... args) throws Exception {
new CompareTest().run(args);
}
public void run(String... args) throws Exception {
old_javah_cmd = new File(args[0]);
rt_jar = new File(args[1]);
Set<String> testClasses;
if (args.length > 2) {
testClasses = new LinkedHashSet<String>(Arrays.asList(Arrays.copyOfRange(args, 2, args.length)));
} else
testClasses = getNativeClasses(new JarFile(rt_jar));
for (String[] options: testCases) {
for (String name: testClasses) {
test(Arrays.asList(options), rt_jar, name);
}
}
if (errors == 0)
System.out.println(count + " tests passed");
else
throw new Exception(errors + "/" + count + " tests failed");
}
public void test(List<String> options, File bootclasspath, String className)
throws IOException, InterruptedException {
System.err.println("test: " + options + " " + className);
count++;
testOptions = options;
testClassName = className;
File oldOutDir = initDir(file(new File("old"), className));
int old_rc = old_javah(options, oldOutDir, bootclasspath, className);
File newOutDir = initDir(file(new File("new"), className));
int new_rc = new_javah(options, newOutDir, bootclasspath, className);
if (old_rc != new_rc)
error("return codes differ; old: " + old_rc + ", new: " + new_rc);
compare(oldOutDir, newOutDir);
}
int old_javah(List<String> options, File outDir, File bootclasspath, String className)
throws IOException, InterruptedException {
List<String> cmd = new ArrayList<String>();
cmd.add(old_javah_cmd.getPath());
cmd.addAll(options);
cmd.add("-d");
cmd.add(outDir.getPath());
cmd.add("-bootclasspath");
cmd.add(bootclasspath.getPath());
cmd.add(className);
System.err.println("old_javah: " + cmd);
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
StringBuilder sb = new StringBuilder();
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
System.err.println("old javah out: " + sb.toString());
return p.waitFor();
}
int new_javah(List<String> options, File outDir, File bootclasspath, String className) {
List<String> args = new ArrayList<String>();
args.addAll(options);
args.add("-d");
args.add(outDir.getPath());
args.add("-bootclasspath");
args.add(bootclasspath.getPath());
args.add(className);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), pw);
pw.close();
System.err.println("new javah out: " + sw.toString());
return rc;
}
Set<String> getNativeClasses(JarFile jar) throws IOException, ConstantPoolException {
System.err.println("getNativeClasses: " + jar.getName());
Set<String> results = new TreeSet<String>();
Enumeration<JarEntry> e = jar.entries();
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if (isNativeClass(jar, je)) {
String name = je.getName();
results.add(name.substring(0, name.length() - 6).replace("/", "."));
}
}
return results;
}
boolean isNativeClass(JarFile jar, JarEntry entry) throws IOException, ConstantPoolException {
String name = entry.getName();
if (name.startsWith("META-INF") || !name.endsWith(".class"))
return false;
//String className = name.substring(0, name.length() - 6).replace("/", ".");
//System.err.println("check " + className);
InputStream in = jar.getInputStream(entry);
ClassFile cf = ClassFile.read(in);
for (int i = 0; i < cf.methods.length; i++) {
Method m = cf.methods[i];
if (m.access_flags.is(AccessFlags.ACC_NATIVE)) {
// System.err.println(className);
return true;
}
}
return false;
}
void compare(File f1, File f2) throws IOException {
if (f1.isFile() && f2.isFile())
compareFiles(f1, f2);
else if (f1.isDirectory() && f2.isDirectory())
compareDirectories(f1, f2);
else
error("files differ: "
+ f1 + " (" + getFileType(f1) + "), "
+ f2 + " (" + getFileType(f2) + ")");
}
void compareDirectories(File d1, File d2) throws IOException {
Set<String> list = new TreeSet<String>();
list.addAll(Arrays.asList(d1.list()));
list.addAll(Arrays.asList(d2.list()));
for (String c: list)
compare(new File(d1, c), new File(d2, c));
}
void compareFiles(File f1, File f2) throws IOException {
byte[] c1 = readFile(f1);
byte[] c2 = readFile(f2);
if (!Arrays.equals(c1, c2))
error("files differ: " + f1 + ", " + f2);
}
byte[] readFile(File file) throws IOException {
int size = (int) file.length();
byte[] data = new byte[size];
DataInputStream in = new DataInputStream(new FileInputStream(file));
try {
in.readFully(data);
} finally {
in.close();
}
return data;
}
String getFileType(File f) {
return f.isDirectory() ? "directory"
: f.isFile() ? "file"
: f.exists() ? "other"
: "not found";
}
/**
* Set up an empty directory.
*/
public File initDir(File dir) {
if (dir.exists())
deleteAll(dir);
dir.mkdirs();
return dir;
}
/**
* Delete a file or a directory (including all its contents).
*/
boolean deleteAll(File file) {
if (file.isDirectory()) {
for (File f: file.listFiles())
deleteAll(f);
}
return file.delete();
}
File file(File dir, String... path) {
File f = dir;
for (String p: path)
f = new File(f, p);
return f;
}
/**
* Report an error.
*/
void error(String msg, String... more) {
System.err.println("test: " + testOptions + " " + testClassName);
System.err.println("error: " + msg);
for (String s: more)
System.err.println(s);
errors++;
System.exit(1);
}
File old_javah_cmd;
File rt_jar;
List<String> testOptions;
String testClassName;
int count;
int errors;
}

View file

@ -1,12 +1,11 @@
#!/bin/sh
#
# Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun in the LICENSE file that accompanied this code.
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@ -23,5 +22,22 @@
# have any questions.
#
pack.pragma.start=\#pragma pack(4)\n
pack.pragma.end=\#pragma pack()\n
jdk=${1:-/opt/jdk/1.6.0}
javah=${jdk}/bin/javah
rtjar=${jdk}/jre/lib/rt.jar
# compile test
mkdir -p build/compareTest
/opt/jdk/1.7.0/bin/javac -classpath build/classes -d build/compareTest test/tools/javah/compareTest/*.java
# run test
/opt/jdk/1.7.0/bin/java -classpath build/compareTest:build/classes CompareTest $javah $rtjar 2>&1 | tee CompareTest.out
# show diffs for tests that failed
grep 'error:' CompareTest.out | sed -e 's|.*new/||' -e 's/\.h$//' -e 's|_|.|g' > CompareTest.classes.fail
for i in $(cat CompareTest.classes.fail) ; do
/opt/jdk/1.7.0/bin/java -classpath compareTest:build/classes CompareTest $javah $rtjar $i
diff -r old new
done

View file

@ -0,0 +1,86 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.sun.tools.classfile.AccessFlags;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Method;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class FindNativeFiles {
public static void main(String[] args) throws IOException, ConstantPoolException {
new FindNativeFiles().run(args);
}
public void run(String[] args) throws IOException, ConstantPoolException {
JarFile jar = new JarFile(args[0]);
Set<JarEntry> entries = getNativeClasses(jar);
for (JarEntry e: entries) {
String name = e.getName();
String className = name.substring(0, name.length() - 6).replace("/", ".");
System.out.println(className);
}
}
Set<JarEntry> getNativeClasses(JarFile jar) throws IOException, ConstantPoolException {
Set<JarEntry> results = new TreeSet<JarEntry>(new Comparator<JarEntry>() {
public int compare(JarEntry o1, JarEntry o2) {
return o1.getName().compareTo(o2.getName());
}
});
Enumeration<JarEntry> e = jar.entries();
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if (isNativeClass(jar, je))
results.add(je);
}
return results;
}
boolean isNativeClass(JarFile jar, JarEntry entry) throws IOException, ConstantPoolException {
String name = entry.getName();
if (name.startsWith("META-INF") || !name.endsWith(".class"))
return false;
//String className = name.substring(0, name.length() - 6).replace("/", ".");
//System.err.println("check " + className);
InputStream in = jar.getInputStream(entry);
ClassFile cf = ClassFile.read(in);
in.close();
for (int i = 0; i < cf.methods.length; i++) {
Method m = cf.methods[i];
if (m.access_flags.is(AccessFlags.ACC_NATIVE)) {
// System.err.println(className);
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,16 @@
test/tools/javah/compareTest/README
This directory contains a program for comparing the output of new javah against the
output of JDK 6 or other older versions of javah.
It cannot be run automatically because of the need for the older version of javah
to compare against.
The test works by scanning a jar file, such as rt.jar, looking for all files with
native methods. It then runs both the old and new versions of javah on those
classes with native methods, and verifies that the results are character-for-character
identical.
To run the test, build langtools, then execute the script in the root langtools
directory, providing the location of the JDK to be tested. The default is
/opt/jdk/1.6.0.