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"/> jarclasspath="javadoc.jar doclets.jar javac.jar"/>
</target> </target>
<target name="build-javah" depends="build-javadoc"> <target name="build-javah" depends="build-javac">
<build-tool name="javah" <build-tool name="javah"
includes="${javah.includes}" includes="${javah.includes}"
jarclasspath="javadoc.jar doclets.jar javac.jar"/> jarclasspath="javac.jar"/>
</target> </target>
<target name="build-classes-javah" depends="build-classes-javadoc"> <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.UnsupportedEncodingException;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
import com.sun.javadoc.*; import java.util.ArrayList;
import java.io.*;
import java.util.Stack;
import java.util.Vector;
import java.util.Arrays; 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. * 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 * original writing, this interface is rich enough to support JNI and the
* old 1.0-style native method interface. * 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) * @author Sucheta Dambalkar(Revised)
*/ */
public abstract class Gen { public abstract class Gen {
protected String lineSep = System.getProperty("line.separator"); 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. * List of classes for which we must generate output.
*/ */
protected ClassDoc[] classes; protected Set<TypeElement> classes;
static private final boolean isWindows = static private final boolean isWindows =
System.getProperty("os.name").startsWith("Windows"); System.getProperty("os.name").startsWith("Windows");
public Gen(RootDoc root){
this.root = root;
}
/** /**
* Override this abstract method, generating content for the named * Override this abstract method, generating content for the named
* class into the outputstream. * class into the outputstream.
*/ */
protected abstract void write(OutputStream o, ClassDoc clazz) protected abstract void write(OutputStream o, TypeElement clazz) throws Util.Exit;
throws ClassNotFoundException;
/** /**
* Override this method to provide a list of #include statements * Override this method to provide a list of #include statements
@ -78,31 +103,29 @@ public abstract class Gen {
/* /*
* Output location. * Output location.
*/ */
protected String outDir; protected JavaFileManager fileManager;
protected String outFile; protected JavaFileObject outFile;
public void setOutDir(String outDir) { public void setFileManager(JavaFileManager fm) {
/* Check important, otherwise concatenation of two null strings fileManager = fm;
* 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 setOutFile(String outFile) { public void setOutFile(JavaFileObject outFile) {
this.outFile = outFile; this.outFile = outFile;
} }
public void setClasses(ClassDoc[] classes) { public void setClasses(Set<TypeElement> classes) {
this.classes = 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. * Smartness with generated files.
*/ */
@ -116,12 +139,11 @@ public abstract class Gen {
* We explicitly need to write ASCII files because that is what C * We explicitly need to write ASCII files because that is what C
* compilers understand. * compilers understand.
*/ */
protected PrintWriter wrapWriter(OutputStream o) { protected PrintWriter wrapWriter(OutputStream o) throws Util.Exit {
try { try {
return new return new PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
PrintWriter(new OutputStreamWriter(o, "ISO8859_1"), true);
} catch (UnsupportedEncodingException use) { } catch (UnsupportedEncodingException use) {
Util.bug("encoding.iso8859_1.not.found"); util.bug("encoding.iso8859_1.not.found");
return null; /* dead code */ return null; /* dead code */
} }
} }
@ -133,26 +155,25 @@ public abstract class Gen {
* Buffer size chosen as an approximation from a single sampling of: * Buffer size chosen as an approximation from a single sampling of:
* expr `du -sk` / `ls *.h | wc -l` * expr `du -sk` / `ls *.h | wc -l`
*/ */
public void run() throws IOException, ClassNotFoundException { public void run() throws IOException, ClassNotFoundException, Util.Exit {
int i = 0; int i = 0;
if (outFile != null) { if (outFile != null) {
/* Everything goes to one big file... */ /* Everything goes to one big file... */
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192); ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
writeFileTop(bout); /* only once */ writeFileTop(bout); /* only once */
for (i = 0; i < classes.length; i++) { for (TypeElement t: classes) {
write(bout, classes[i]); write(bout, t);
} }
writeIfChanged(bout.toByteArray(), outFile); writeIfChanged(bout.toByteArray(), outFile);
} else { } else {
/* Each class goes to its own file... */ /* Each class goes to its own file... */
for (i = 0; i < classes.length; i++) { for (TypeElement t: classes) {
ByteArrayOutputStream bout = new ByteArrayOutputStream(8192); ByteArrayOutputStream bout = new ByteArrayOutputStream(8192);
writeFileTop(bout); writeFileTop(bout);
ClassDoc clazz = classes[i]; write(bout, t);
write(bout, clazz); writeIfChanged(bout.toByteArray(), getFileObject(t.getQualifiedName()));
writeIfChanged(bout.toByteArray(), getFileName(clazz.qualifiedName()));
} }
} }
} }
@ -162,8 +183,7 @@ public abstract class Gen {
* is done if either the file doesn't exist or if the contents are * is done if either the file doesn't exist or if the contents are
* different. * different.
*/ */
private void writeIfChanged(byte[] b, String file) throws IOException { private void writeIfChanged(byte[] b, FileObject file) throws IOException {
File f = new File(file);
boolean mustWrite = false; boolean mustWrite = false;
String event = "[No need to update file "; String event = "[No need to update file ";
@ -171,71 +191,80 @@ public abstract class Gen {
mustWrite = true; mustWrite = true;
event = "[Forcefully writing file "; event = "[Forcefully writing file ";
} else { } else {
if (!f.exists()) { InputStream in;
mustWrite = true; byte[] a;
event = "[Creating file "; try {
} else { // regrettably, there's no API to get the length in bytes
int l = (int)f.length(); // for a FileObject, so we can't short-circuit reading the
if (b.length != l) { // file here
in = file.openInputStream();
a = readBytes(in);
if (!Arrays.equals(a, b)) {
mustWrite = true; mustWrite = true;
event = "[Overwriting file "; 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 ";
}
}
} }
} catch (FileNotFoundException e) {
mustWrite = true;
event = "[Creating file ";
} }
} }
if (Util.verbose)
Util.log(event + file + "]"); if (util.verbose)
util.log(event + file + "]");
if (mustWrite) { if (mustWrite) {
OutputStream out = new FileOutputStream(file); OutputStream out = file.openOutputStream();
out.write(b); /* No buffering, just one big write! */ out.write(b); /* No buffering, just one big write! */
out.close(); 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(); return Arrays.copyOf(array, offset);
String fnamedoc = f.name(); } finally {
in.close();
}
}
String cname = Mangle.mangle(cnamedoc, Mangle.Type.CLASS); protected String defineForStatic(TypeElement c, VariableElement f)
String fname = Mangle.mangle(fnamedoc, Mangle.Type.FIELDSTUB); throws Util.Exit {
CharSequence cnamedoc = c.getQualifiedName();
CharSequence fnamedoc = f.getSimpleName();
if (!f.isStatic()) String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
Util.bug("tried.to.define.non.static"); 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; Object value = null;
value = f.constantValue(); value = f.getConstantValue();
if (value != null) { /* so it is a ConstantExpression */ if (value != null) { /* so it is a ConstantExpression */
String constString = null; String constString = null;
if ((value instanceof Integer) if ((value instanceof Integer)
|| (value instanceof Byte) || (value instanceof Byte)
|| (value instanceof Character) || (value instanceof Short)) {
|| (value instanceof Short) /* covers byte, short, int */
|| (value instanceof Boolean)) { constString = value.toString() + "L";
/* covers byte, boolean, char, short, int */ } else if (value instanceof Boolean) {
if(value instanceof Boolean) constString = ((Boolean) value) ? "1L" : "0L";
constString = (value.toString() == "true") ? "1L" : "0L"; } else if (value instanceof Character) {
else Character ch = (Character) value;
constString = value.toString() + "L"; constString = String.valueOf(((int) ch) & 0xffff) + "L";
} else if (value instanceof Long) { } else if (value instanceof Long) {
// Visual C++ supports the i64 suffix, not LL. // Visual C++ supports the i64 suffix, not LL.
if (isWindows) if (isWindows)
@ -294,24 +323,19 @@ public abstract class Gen {
/* /*
* File name and file preamble related operations. * File name and file preamble related operations.
*/ */
protected void writeFileTop(OutputStream o) { protected void writeFileTop(OutputStream o) throws Util.Exit {
PrintWriter pw = wrapWriter(o); PrintWriter pw = wrapWriter(o);
pw.println("/* DO NOT EDIT THIS FILE - it is machine generated */" + lineSep + pw.println("/* DO NOT EDIT THIS FILE - it is machine generated */" + lineSep +
getIncludes()); getIncludes());
} }
protected String baseFileName(String clazz) { protected String baseFileName(CharSequence className) {
StringBuffer f = return mangler.mangle(className, Mangle.Type.CLASS);
new StringBuffer(Mangle.mangle(clazz,
Mangle.Type.CLASS));
if (outDir != null) {
f.insert(0, outDir);
}
return f.toString();
} }
protected String getFileName(String clazz) { protected FileObject getFileObject(CharSequence className) throws IOException {
return baseFileName(clazz) + getFileSuffix(); String name = baseFileName(className) + getFileSuffix();
return fileManager.getFileForOutput(StandardLocation.SOURCE_OUTPUT, "", name, null);
} }
protected String getFileSuffix() { protected String getFileSuffix() {
@ -322,26 +346,39 @@ public abstract class Gen {
* Including super classes' fields. * Including super classes' fields.
*/ */
FieldDoc[] getAllFields(ClassDoc subclazz) List<VariableElement> getAllFields(TypeElement subclazz) {
throws ClassNotFoundException { List<VariableElement> fields = new ArrayList<VariableElement>();
Vector<FieldDoc> fields = new Vector<FieldDoc>(); TypeElement cd = null;
ClassDoc cd = null; Stack<TypeElement> s = new Stack<TypeElement>();
Stack<Object> s = new Stack<Object>();
cd = subclazz; cd = subclazz;
while (true) { while (true) {
s.push(cd); s.push(cd);
ClassDoc c = cd.superclass(); TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
if (c == null) if (c == null)
break; break;
cd = c; cd = c;
} }
while (!s.empty()) { while (!s.empty()) {
cd = (ClassDoc)s.pop(); cd = s.pop();
fields.addAll(Arrays.asList(cd.fields())); 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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.OutputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Vector; import java.util.ArrayList;
import java.util.Enumeration; import java.util.List;
import com.sun.javadoc.*; 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. * 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) * @author Sucheta Dambalkar(Revised)
*/ */
public class JNI extends Gen { public class JNI extends Gen {
JNI(Util util) {
public JNI(RootDoc root){ super(util);
super(root);
} }
public String getIncludes() { public String getIncludes() {
return "#include <jni.h>"; return "#include <jni.h>";
} }
public void write(OutputStream o, ClassDoc clazz) public void write(OutputStream o, TypeElement clazz) throws Util.Exit {
throws ClassNotFoundException { String cname = mangler.mangle(clazz.getQualifiedName(), Mangle.Type.CLASS);
String cname = Mangle.mangle(clazz.qualifiedName(), Mangle.Type.CLASS);
PrintWriter pw = wrapWriter(o); PrintWriter pw = wrapWriter(o);
pw.println(guardBegin(cname)); pw.println(guardBegin(cname));
pw.println(cppGuardBegin()); pw.println(cppGuardBegin());
/* Write statics. */ /* Write statics. */
FieldDoc[] classfields = getAllFields(clazz); List<VariableElement> classfields = getAllFields(clazz);
for (int i = 0; i < classfields.length; i++) { for (VariableElement v: classfields) {
if (!classfields[i].isStatic()) if (!v.getModifiers().contains(Modifier.STATIC))
continue; continue;
String s = null; String s = null;
s = defineForStatic(clazz, classfields[i]); s = defineForStatic(clazz, v);
if (s != null) { if (s != null) {
pw.println(s); pw.println(s);
} }
} }
/* Write methods. */ /* Write methods. */
MethodDoc[] classmethods = clazz.methods(); List<ExecutableElement> classmethods = ElementFilter.methodsIn(clazz.getEnclosedElements());
for (int i = 0; i < classmethods.length; i++) { for (ExecutableElement md: classmethods) {
if(classmethods[i].isNative()){ if(md.getModifiers().contains(Modifier.NATIVE)){
MethodDoc md = classmethods[i]; TypeMirror mtr = types.erasure(md.getReturnType());
Type mtr = classmethods[i].returnType(); String sig = signature(md);
String sig = md.signature(); TypeSignature newtypesig = new TypeSignature(elems);
TypeSignature newtypesig = new TypeSignature(root); CharSequence methodName = md.getSimpleName();
String methodName = md.name();
boolean longName = false; boolean longName = false;
for (int j = 0; j < classmethods.length; j++) { for (ExecutableElement md2: classmethods) {
if ((classmethods[j] != md) if ((md2 != md)
&& (methodName.equals(classmethods[j].name())) && (methodName.equals(md2.getSimpleName()))
&& (classmethods[j].isNative())) && (md2.getModifiers().contains(Modifier.NATIVE)))
longName = true; longName = true;
} }
pw.println("/*"); pw.println("/*");
pw.println(" * Class: " + cname); pw.println(" * Class: " + cname);
pw.println(" * Method: " + pw.println(" * Method: " +
Mangle.mangle(methodName, Mangle.Type.FIELDSTUB)); mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr)); pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr));
pw.println(" */"); pw.println(" */");
pw.println("JNIEXPORT " + jniType(mtr) + pw.println("JNIEXPORT " + jniType(mtr) +
" JNICALL " + " JNICALL " +
Mangle.mangleMethod(md, root,clazz, mangler.mangleMethod(md, clazz,
(longName) ? (longName) ?
Mangle.Type.METHOD_JNI_LONG : Mangle.Type.METHOD_JNI_LONG :
Mangle.Type.METHOD_JNI_SHORT)); Mangle.Type.METHOD_JNI_SHORT));
pw.print(" (JNIEnv *, "); pw.print(" (JNIEnv *, ");
Parameter[] paramargs = md.parameters(); List<? extends VariableElement> paramargs = md.getParameters();
Type []args =new Type[ paramargs.length]; List<TypeMirror> args = new ArrayList<TypeMirror>();
for(int p = 0; p < paramargs.length; p++){ for (VariableElement p: paramargs) {
args[p] = paramargs[p].type(); args.add(types.erasure(p.asType()));
} }
if (md.isStatic()) if (md.getModifiers().contains(Modifier.STATIC))
pw.print("jclass"); pw.print("jclass");
else else
pw.print("jobject"); pw.print("jobject");
if (args.length > 0)
pw.print(", ");
for (int j = 0; j < args.length; j++) { for (TypeMirror arg: args) {
pw.print(jniType(args[j])); pw.print(", ");
if (j != (args.length - 1)) { pw.print(jniType(arg));
pw.print(", ");
}
} }
pw.println(");" + lineSep); 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){ switch (t.getKind()) {
if((t.dimension().indexOf("[][]") != -1) case ARRAY: {
|| (tclassDoc != null)) return "jobjectArray"; TypeMirror ct = ((ArrayType) t).getComponentType();
else if(elmT.equals("boolean"))return "jbooleanArray"; switch (ct.getKind()) {
else if(elmT.equals("byte"))return "jbyteArray"; case BOOLEAN: return "jbooleanArray";
else if(elmT.equals("char"))return "jcharArray"; case BYTE: return "jbyteArray";
else if(elmT.equals("short"))return "jshortArray"; case CHAR: return "jcharArray";
else if(elmT.equals("int"))return "jintArray"; case SHORT: return "jshortArray";
else if(elmT.equals("long"))return "jlongArray"; case INT: return "jintArray";
else if(elmT.equals("float"))return "jfloatArray"; case LONG: return "jlongArray";
else if(elmT.equals("double"))return "jdoubleArray"; case FLOAT: return "jfloatArray";
}else{ case DOUBLE: return "jdoubleArray";
if(elmT.equals("void"))return "void"; case ARRAY:
else if(elmT.equals("String"))return "jstring"; case DECLARED: return "jobjectArray";
else if(elmT.equals("boolean"))return "jboolean"; default: throw new Error(ct.toString());
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"; case VOID: return "void";
else if(elmT.equals("long"))return "jlong"; case BOOLEAN: return "jboolean";
else if(elmT.equals("float"))return "jfloat"; case BYTE: return "jbyte";
else if(elmT.equals("double"))return "jdouble"; case CHAR: return "jchar";
else if(tclassDoc != null){ case SHORT: return "jshort";
if(tclassDoc.subclassOf(throwable)) return "jthrowable"; case INT: return "jint";
else if(tclassDoc.subclassOf(jClass)) return "jclass"; case LONG: return "jlong";
else return "jobject"; 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");
util.bug("jni.unknown.type");
return null; /* dead code. */ 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,49 +26,65 @@
package com.sun.tools.javah; package com.sun.tools.javah;
import java.io.File;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Hashtable; import java.util.ArrayList;
import com.sun.javadoc.*; import java.util.HashSet;
import java.util.List;
/* import java.util.Set;
* @author Sucheta Dambalkar(Revised) 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 { public class LLNI extends Gen {
protected final char pathChar = File.separatorChar;
protected final char innerDelim = '$'; /* For inner classes */ protected final char innerDelim = '$'; /* For inner classes */
protected Hashtable<Object, Object> doneHandleTypes; protected Set<String> doneHandleTypes;
MemberDoc []fields; List<VariableElement> fields;
MemberDoc [] methods; List<ExecutableElement> methods;
private boolean doubleAlign; private boolean doubleAlign;
private int padFieldNum = 0; private int padFieldNum = 0;
LLNI(boolean doubleAlign, Util util) {
LLNI(boolean doubleAlign, RootDoc root) { super(util);
super(root);
this.doubleAlign = doubleAlign; this.doubleAlign = doubleAlign;
} }
protected String getIncludes() { protected String getIncludes() {
return ""; return "";
} }
protected void write(OutputStream o, ClassDoc clazz) protected void write(OutputStream o, TypeElement clazz) throws Util.Exit {
throws ClassNotFoundException { String cname = mangleClassName(clazz.getQualifiedName().toString());
String cname = mangleClassName(clazz.qualifiedName());
PrintWriter pw = wrapWriter(o); PrintWriter pw = wrapWriter(o);
fields = clazz.fields(); fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
methods = clazz.methods(); methods = ElementFilter.methodsIn(clazz.getEnclosedElements());
generateDeclsForClass(pw, clazz, cname); generateDeclsForClass(pw, clazz, cname);
// FIXME check if errors occurred on the PrintWriter and throw exception if so
} }
protected void generateDeclsForClass(PrintWriter pw, protected void generateDeclsForClass(PrintWriter pw,
ClassDoc clazz, String cname) TypeElement clazz, String cname) throws Util.Exit {
throws ClassNotFoundException { doneHandleTypes = new HashSet<String>();
doneHandleTypes = new Hashtable<Object, Object>();
/* The following handle types are predefined in "typedefs.h". Suppress /* The following handle types are predefined in "typedefs.h". Suppress
inclusion in the output by generating them "into the blue" here. */ inclusion in the output by generating them "into the blue" here. */
genHandleType(null, "java.lang.Class"); genHandleType(null, "java.lang.Class");
@ -79,7 +95,7 @@ public class LLNI extends Gen {
genHandleType(null, "java.lang.ThreadGroup"); genHandleType(null, "java.lang.ThreadGroup");
genHandleType(null, "java.lang.Throwable"); 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("#ifndef _Included_" + cname);
pw.println("#define _Included_" + cname); pw.println("#define _Included_" + cname);
pw.println("#include \"typedefs.h\""); pw.println("#include \"typedefs.h\"");
@ -94,8 +110,8 @@ public class LLNI extends Gen {
protected void genHandleType(PrintWriter pw, String clazzname) { protected void genHandleType(PrintWriter pw, String clazzname) {
String cname = mangleClassName(clazzname); String cname = mangleClassName(clazzname);
if (!doneHandleTypes.containsKey(cname)) { if (!doneHandleTypes.contains(cname)) {
doneHandleTypes.put(cname, cname); doneHandleTypes.add(cname);
if (pw != null) { if (pw != null) {
pw.println("#ifndef DEFINED_" + cname); pw.println("#ifndef DEFINED_" + cname);
pw.println(" #define DEFINED_" + cname); pw.println(" #define DEFINED_" + cname);
@ -107,31 +123,29 @@ public class LLNI extends Gen {
protected String mangleClassName(String s) { protected String mangleClassName(String s) {
return s.replace('.', '_') return s.replace('.', '_')
.replace(pathChar, '_') .replace('/', '_')
.replace(innerDelim, '_'); .replace(innerDelim, '_');
} }
protected void forwardDecls(PrintWriter pw, ClassDoc clazz) protected void forwardDecls(PrintWriter pw, TypeElement clazz) {
throws ClassNotFoundException { TypeElement object = elems.getTypeElement("java.lang.Object");
ClassDoc clazzfield = null; if (clazz.equals(object))
if (clazz.qualifiedName().equals("java.lang.Object"))
return; return;
genHandleType(pw, clazz.qualifiedName());
ClassDoc superClass = clazz.superclass();
if(superClass != null){ genHandleType(pw, clazz.getQualifiedName().toString());
String superClassName = superClass.qualifiedName(); TypeElement superClass = (TypeElement) (types.asElement(clazz.getSuperclass()));
if (superClass != null) {
String superClassName = superClass.getQualifiedName().toString();
forwardDecls(pw, superClass); forwardDecls(pw, superClass);
} }
for (int i = 0; i < fields.length; i++) { for (VariableElement field: fields) {
FieldDoc field = (FieldDoc)fields[i];
if (!field.isStatic()) { if (!field.getModifiers().contains(Modifier.STATIC)) {
Type t = field.type(); TypeMirror t = types.erasure(field.asType());
String tname = t.qualifiedTypeName(); TypeSignature newTypeSig = new TypeSignature(elems);
TypeSignature newTypeSig = new TypeSignature(root); String tname = newTypeSig.qualifiedTypeName(t);
String sig = newTypeSig.getTypeSignature(tname); String sig = newTypeSig.getTypeSignature(tname);
if (sig.charAt(0) != '[') if (sig.charAt(0) != '[')
@ -139,13 +153,12 @@ public class LLNI extends Gen {
} }
} }
for (int i = 0; i < methods.length; i++) { for (ExecutableElement method: methods) {
MethodDoc method = (MethodDoc)methods[i];
if (method.isNative()) { if (method.getModifiers().contains(Modifier.NATIVE)) {
Type retType = method.returnType(); TypeMirror retType = types.erasure(method.getReturnType());
String typesig = method.signature(); String typesig = signature(method);
TypeSignature newTypeSig = new TypeSignature(root); TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(typesig, retType); String sig = newTypeSig.getTypeSignature(typesig, retType);
if (sig.charAt(0) != '[') if (sig.charAt(0) != '[')
@ -173,10 +186,9 @@ public class LLNI extends Gen {
} }
protected void structSectionForClass(PrintWriter pw, protected void structSectionForClass(PrintWriter pw,
ClassDoc jclazz, String cname) TypeElement jclazz, String cname) {
throws ClassNotFoundException {
String jname = jclazz.qualifiedName(); String jname = jclazz.getQualifiedName().toString();
if (cname.equals("java_lang_Object")) { if (cname.equals("java_lang_Object")) {
pw.println("/* struct java_lang_Object is defined in typedefs.h. */"); 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 bottomMost;
public boolean printedOne = false; public boolean printedOne = false;
FieldDefsRes(ClassDoc clazz, FieldDefsRes parent, boolean bottomMost) { FieldDefsRes(TypeElement clazz, FieldDefsRes parent, boolean bottomMost) {
this.className = clazz.qualifiedName(); this.className = clazz.getQualifiedName().toString();
this.parent = parent; this.parent = parent;
this.bottomMost = bottomMost; this.bottomMost = bottomMost;
int byteSize = 0; int byteSize = 0;
@ -218,9 +230,8 @@ public class LLNI extends Gen {
} }
/* Returns "true" iff added a field. */ /* Returns "true" iff added a field. */
private boolean doField(FieldDefsRes res, FieldDoc field, private boolean doField(FieldDefsRes res, VariableElement field,
String cname, boolean padWord) String cname, boolean padWord) {
throws ClassNotFoundException {
String fieldDef = addStructMember(field, cname, padWord); String fieldDef = addStructMember(field, cname, padWord);
if (fieldDef != null) { if (fieldDef != null) {
@ -242,16 +253,14 @@ public class LLNI extends Gen {
return false; return false;
} }
private int doTwoWordFields(FieldDefsRes res, ClassDoc clazz, private int doTwoWordFields(FieldDefsRes res, TypeElement clazz,
int offset, String cname, boolean padWord) int offset, String cname, boolean padWord) {
throws ClassNotFoundException {
boolean first = true; boolean first = true;
FieldDoc[] fields = clazz.fields(); List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
for (int i = 0; i <fields.length; i++) { for (VariableElement field: fields) {
FieldDoc field = fields[i]; TypeKind tk = field.asType().getKind();
String tc =field.type().typeName(); boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
boolean twoWords = (tc.equals("long") || tc.equals("double"));
if (twoWords && doField(res, field, cname, first && padWord)) { if (twoWords && doField(res, field, cname, first && padWord)) {
offset += 8; first = false; offset += 8; first = false;
} }
@ -259,22 +268,21 @@ public class LLNI extends Gen {
return offset; return offset;
} }
protected String fieldDefs(ClassDoc clazz, String cname) String fieldDefs(TypeElement clazz, String cname) {
throws ClassNotFoundException {
FieldDefsRes res = fieldDefs(clazz, cname, true); FieldDefsRes res = fieldDefs(clazz, cname, true);
return res.s; return res.s;
} }
protected FieldDefsRes fieldDefs(ClassDoc clazz, String cname, FieldDefsRes fieldDefs(TypeElement clazz, String cname,
boolean bottomMost) boolean bottomMost){
throws ClassNotFoundException {
FieldDefsRes res; FieldDefsRes res;
int offset; int offset;
boolean didTwoWordFields = false; boolean didTwoWordFields = false;
ClassDoc superclazz = clazz.superclass();
TypeElement superclazz = (TypeElement) types.asElement(clazz.getSuperclass());
if (superclazz != null) { if (superclazz != null) {
String supername = superclazz.qualifiedName(); String supername = superclazz.getQualifiedName().toString();
res = new FieldDefsRes(clazz, res = new FieldDefsRes(clazz,
fieldDefs(superclazz, cname, false), fieldDefs(superclazz, cname, false),
bottomMost); bottomMost);
@ -284,18 +292,17 @@ public class LLNI extends Gen {
offset = 0; offset = 0;
} }
FieldDoc[] fields = clazz.fields(); List<VariableElement> fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
for (int i = 0; i < fields.length; i++) { for (VariableElement field: fields) {
FieldDoc field = fields[i];
if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) { if (doubleAlign && !didTwoWordFields && (offset % 8) == 0) {
offset = doTwoWordFields(res, clazz, offset, cname, false); offset = doTwoWordFields(res, clazz, offset, cname, false);
didTwoWordFields = true; didTwoWordFields = true;
} }
String tc = field.type().typeName(); TypeKind tk = field.asType().getKind();
boolean twoWords = (tc.equals("long") ||tc.equals("double")); boolean twoWords = (tk == TypeKind.LONG || tk == TypeKind.DOUBLE);
if (!doubleAlign || !twoWords) { if (!doubleAlign || !twoWords) {
if (doField(res, field, cname, false)) offset += 4; if (doField(res, field, cname, false)) offset += 4;
@ -313,19 +320,19 @@ public class LLNI extends Gen {
} }
/* OVERRIDE: This method handles instance fields */ /* OVERRIDE: This method handles instance fields */
protected String addStructMember(FieldDoc member, String cname, protected String addStructMember(VariableElement member, String cname,
boolean padWord) boolean padWord) {
throws ClassNotFoundException {
String res = null; String res = null;
if (member.isStatic()) { if (member.getModifiers().contains(Modifier.STATIC)) {
res = addStaticStructMember(member, cname); res = addStaticStructMember(member, cname);
// if (res == null) /* JNI didn't handle it, print comment. */ // if (res == null) /* JNI didn't handle it, print comment. */
// res = " /* Inaccessible static: " + member + " */" + lineSep; // res = " /* Inaccessible static: " + member + " */" + lineSep;
} else { } else {
TypeMirror mt = types.erasure(member.asType());
if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep; if (padWord) res = " java_int padWord" + padFieldNum++ + ";" + lineSep;
res = " " + llniType(member.type(), false, false) + " " + llniFieldName(member); res = " " + llniType(mt, false, false) + " " + llniFieldName(member);
if (isLongOrDouble(member.type())) res = res + "[2]"; if (isLongOrDouble(mt)) res = res + "[2]";
res = res + ";" + lineSep; res = res + ";" + lineSep;
} }
return res; return res;
@ -337,36 +344,42 @@ public class LLNI extends Gen {
/* /*
* This method only handles static final fields. * This method only handles static final fields.
*/ */
protected String addStaticStructMember(FieldDoc field, String cname) protected String addStaticStructMember(VariableElement field, String cname) {
throws ClassNotFoundException {
String res = null; String res = null;
Object exp = null; Object exp = null;
if (!field.isStatic()) if (!field.getModifiers().contains(Modifier.STATIC))
return res; return res;
if (!field.isFinal()) if (!field.getModifiers().contains(Modifier.FINAL))
return res; return res;
exp = field.constantValue(); exp = field.getConstantValue();
if (exp != null) { if (exp != null) {
/* Constant. */ /* Constant. */
String cn = cname + "_" + field.name(); String cn = cname + "_" + field.getSimpleName();
String suffix = null; String suffix = null;
long val = 0; long val = 0;
/* Can only handle int, long, float, and double fields. */ /* 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"; 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 // Visual C++ supports the i64 suffix, not LL
suffix = isWindows ? "i64" : "LL"; suffix = isWindows ? "i64" : "LL";
val = ((Long)exp).longValue(); val = ((Long)exp).longValue();
} }
if (exp instanceof Float) suffix = "f"; else if (exp instanceof Float) suffix = "f";
if (exp instanceof Double) suffix = ""; else if (exp instanceof Double) suffix = "";
else if (exp instanceof Character) {
suffix = "L";
Character ch = (Character) exp;
val = ((int) ch) & 0xffff;
}
if (suffix != null) { if (suffix != null) {
// Some compilers will generate a spurious warning // Some compilers will generate a spurious warning
// for the integer constants for Integer.MIN_VALUE // for the integer constants for Integer.MIN_VALUE
@ -376,9 +389,12 @@ public class LLNI extends Gen {
res = " #undef " + cn + lineSep res = " #undef " + cn + lineSep
+ " #define " + cn + " #define " + cn
+ " (" + (val + 1) + suffix + "-1)" + lineSep; + " (" + (val + 1) + suffix + "-1)" + lineSep;
} else if (suffix.equals("L") || suffix.endsWith("LL")) {
res = " #undef " + cn + lineSep
+ " #define " + cn + " " + val + suffix + lineSep;
} else { } else {
res = " #undef " + cn + lineSep 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, protected void methodSectionForClass(PrintWriter pw,
ClassDoc clazz, String cname) TypeElement clazz, String cname)
throws ClassNotFoundException { throws Util.Exit {
String methods = methodDecls(clazz, cname); String methods = methodDecls(clazz, cname);
if (methods.length() != 0) { if (methods.length() != 0) {
@ -402,81 +418,77 @@ public class LLNI extends Gen {
} }
} }
protected String methodDecls(ClassDoc clazz, String cname) protected String methodDecls(TypeElement clazz, String cname) throws Util.Exit {
throws ClassNotFoundException {
String res = ""; String res = "";
for (int i = 0; i < methods.length; i++) { for (ExecutableElement method: methods) {
MethodDoc method = (MethodDoc)methods[i]; if (method.getModifiers().contains(Modifier.NATIVE))
if (method.isNative())
res = res + methodDecl(method, clazz, cname); res = res + methodDecl(method, clazz, cname);
} }
return res; return res;
} }
protected String methodDecl(MethodDoc method, protected String methodDecl(ExecutableElement method,
ClassDoc clazz, String cname) TypeElement clazz, String cname)
throws ClassNotFoundException { throws Util.Exit {
String res = null; String res = null;
Type retType = method.returnType(); TypeMirror retType = types.erasure(method.getReturnType());
String typesig = method.signature(); String typesig = signature(method);
TypeSignature newTypeSig = new TypeSignature(root); TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(typesig, retType); String sig = newTypeSig.getTypeSignature(typesig, retType);
boolean longName = needLongName(method, clazz); boolean longName = needLongName(method, clazz);
if (sig.charAt(0) != '(') 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) res = "JNIEXPORT " + jniType(retType) + " JNICALL" + lineSep + jniMethodName(method, cname, longName)
+ "(JNIEnv *, " + cRcvrDecl(method, cname); + "(JNIEnv *, " + cRcvrDecl(method, cname);
Parameter[] params = method.parameters(); List<? extends VariableElement> params = method.getParameters();
Type argTypes[] = new Type[params.length]; List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
for(int p = 0; p < params.length; p++){ for (VariableElement p: params){
argTypes[p] = params[p].type(); argTypes.add(types.erasure(p.asType()));
} }
/* It would have been nice to include the argument names in the /* It would have been nice to include the argument names in the
declaration, but there seems to be a bug in the "BinaryField" declaration, but there seems to be a bug in the "BinaryField"
class, causing the getArguments() method to return "null" for class, causing the getArguments() method to return "null" for
most (non-constructor) methods. */ most (non-constructor) methods. */
for (int i = 0; i < argTypes.length; i++) for (TypeMirror argType: argTypes)
res = res + ", " + jniType(argTypes[i]); res = res + ", " + jniType(argType);
res = res + ");" + lineSep; res = res + ");" + lineSep;
return res; return res;
} }
protected final boolean needLongName(MethodDoc method, protected final boolean needLongName(ExecutableElement method,
ClassDoc clazz) TypeElement clazz) {
throws ClassNotFoundException { Name methodName = method.getSimpleName();
String methodName = method.name(); for (ExecutableElement memberMethod: methods) {
for (int i = 0; i < methods.length; i++) {
MethodDoc memberMethod = (MethodDoc) methods[i];
if ((memberMethod != method) && if ((memberMethod != method) &&
memberMethod.isNative() && (methodName == memberMethod.name())) memberMethod.getModifiers().contains(Modifier.NATIVE) &&
(methodName.equals(memberMethod.getSimpleName())))
return true; return true;
} }
return false; return false;
} }
protected final String jniMethodName(MethodDoc method, String cname, protected final String jniMethodName(ExecutableElement method, String cname,
boolean longName) { boolean longName) {
String res = "Java_" + cname + "_" + method.name(); String res = "Java_" + cname + "_" + method.getSimpleName();
if (longName) { if (longName) {
Type mType = method.returnType(); TypeMirror mType = types.erasure(method.getReturnType());
Parameter[] params = method.parameters(); List<? extends VariableElement> params = method.getParameters();
Type argTypes[] = new Type[params.length]; List<TypeMirror> argTypes = new ArrayList<TypeMirror>();
for(int p = 0; p < params.length; p++){ for (VariableElement param: params) {
argTypes[p] = params[p].type(); argTypes.add(types.erasure(param.asType()));
} }
res = res + "__"; res = res + "__";
for (int i = 0; i < argTypes.length; i++){ for (TypeMirror t: argTypes) {
Type t = argTypes[i]; String tname = t.toString();
String tname = t.typeName(); TypeSignature newTypeSig = new TypeSignature(elems);
TypeSignature newTypeSig = new TypeSignature(root);
String sig = newTypeSig.getTypeSignature(tname); String sig = newTypeSig.getTypeSignature(tname);
res = res + nameToIdentifier(sig); res = res + nameToIdentifier(sig);
} }
@ -484,88 +496,143 @@ public class LLNI extends Gen {
return res; return res;
} }
protected final String jniType(Type t) { // copied from JNI.java
String elmT =t.typeName(); protected final String jniType(TypeMirror t) throws Util.Exit {
if (t.dimension().indexOf("[]") != -1) { TypeElement throwable = elems.getTypeElement("java.lang.Throwable");
if(elmT.equals("boolean"))return "jbooleanArray"; TypeElement jClass = elems.getTypeElement("java.lang.Class");
else if(elmT.equals("byte"))return "jbyteArray"; TypeElement jString = elems.getTypeElement("java.lang.String");
else if(elmT.equals("char"))return "jcharArray"; Element tclassDoc = types.asElement(t);
else if(elmT.equals("short"))return "jshortArray";
else if(elmT.equals("int"))return "jintArray"; switch (t.getKind()) {
else if(elmT.equals("long"))return "jlongArray"; case ARRAY: {
else if(elmT.equals("float"))return "jfloatArray"; TypeMirror ct = ((ArrayType) t).getComponentType();
else if(elmT.equals("double"))return "jdoubleArray"; switch (ct.getKind()) {
else if((t.dimension().indexOf("[][]") != -1) || (t.asClassDoc() != null)) return "jobjectArray"; case BOOLEAN: return "jbooleanArray";
} else { case BYTE: return "jbyteArray";
if(elmT.equals("void"))return "void"; case CHAR: return "jcharArray";
else if(elmT.equals("boolean"))return "jboolean"; case SHORT: return "jshortArray";
else if(elmT.equals("byte"))return "jbyte"; case INT: return "jintArray";
else if(elmT.equals("char"))return "jchar"; case LONG: return "jlongArray";
else if(elmT.equals("short"))return "jshort"; case FLOAT: return "jfloatArray";
else if(elmT.equals("int"))return "jint"; case DOUBLE: return "jdoubleArray";
else if(elmT.equals("long"))return "jlong"; case ARRAY:
else if(elmT.equals("float"))return "jfloat"; case DECLARED: return "jobjectArray";
else if(elmT.equals("double"))return "jdouble"; default: throw new Error(ct.toString());
else if (t.asClassDoc() != null) { }
if (elmT.equals("String")) }
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"; 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"; return "jclass";
else else
return "jobject"; return "jobject";
} }
} }
Util.bug("jni.unknown.type");
util.bug("jni.unknown.type");
return null; /* dead code. */ 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 res = null;
String elmt = t.typeName();
if (t.dimension().indexOf("[]") != -1) { switch (t.getKind()) {
if((t.dimension().indexOf("[][]") != -1) case ARRAY: {
|| (t.asClassDoc() != null)) res = "IArrayOfRef"; TypeMirror ct = ((ArrayType) t).getComponentType();
else if(elmt.equals("boolean")) res = "IArrayOfBoolean"; switch (ct.getKind()) {
else if(elmt.equals("byte")) res = "IArrayOfByte"; case BOOLEAN: res = "IArrayOfBoolean"; break;
else if(elmt.equals("char")) res = "IArrayOfChar"; case BYTE: res = "IArrayOfByte"; break;
else if(elmt.equals("int")) res = "IArrayOfInt"; case CHAR: res = "IArrayOfChar"; break;
else if(elmt.equals("long")) res = "IArrayOfLong"; case SHORT: res = "IArrayOfShort"; break;
else if(elmt.equals("float")) res = "IArrayOfFloat"; case INT: res = "IArrayOfInt"; break;
else if(elmt.equals("double")) res = "IArrayOfDouble"; case LONG: res = "IArrayOfLong"; break;
if (!handleize) res = "DEREFERENCED_" + res; case FLOAT: res = "IArrayOfFloat"; break;
} else { case DOUBLE: res = "IArrayOfDouble"; break;
if(elmt.equals("void")) res = "void"; case ARRAY:
else if( (elmt.equals("boolean")) || (elmt.equals("byte")) case DECLARED: res = "IArrayOfRef"; break;
||(elmt.equals("char")) || (elmt.equals("short")) default: throw new Error(ct.getKind() + " " + ct);
|| (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; 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; return res;
} }
protected final String cRcvrDecl(MemberDoc field, String cname) { protected final String cRcvrDecl(Element field, String cname) {
return (field.isStatic() ? "jclass" : "jobject"); return (field.getModifiers().contains(Modifier.STATIC) ? "jclass" : "jobject");
} }
protected String maskName(String s) { protected String maskName(String s) {
return "LLNI_mask(" + s + ")"; return "LLNI_mask(" + s + ")";
} }
protected String llniFieldName(MemberDoc field) { protected String llniFieldName(VariableElement field) {
return maskName(field.name()); return maskName(field.getSimpleName().toString());
} }
protected final boolean isLongOrDouble(Type t) { protected final boolean isLongOrDouble(TypeMirror t) {
String tc = t.typeName(); TypeVisitor<Boolean,Void> v = new SimpleTypeVisitor6<Boolean,Void>() {
return (tc.equals("long") || tc.equals("double")); 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. /* Do unicode to ansi C identifier conversion.
@ -602,3 +669,4 @@ public class LLNI extends Gen {
return false; 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,134 +23,39 @@
* have any questions. * have any questions.
*/ */
package com.sun.tools.javah; package com.sun.tools.javah;
import java.io.PrintWriter;
import java.io.*;
/** /**
* Javah generates support files for native methods. * Main entry point.
* Parse commandline options & Invokes javadoc to execute those commands.
* *
* @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{ public class Main {
/* /**
* Parse arguments given for javah to give proper error messages. * Main entry point for the launcher.
* Note: This method calls System.exit.
* @param args command line arguments
*/ */
public static void main(String[] args){ public static void main(String[] args) {
JavahTask t = new JavahTask();
if (args.length == 0) { int rc = t.run(args);
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);
System.exit(rc); 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,22 +26,30 @@
package com.sun.tools.javah; 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 * A utility for mangling java identifiers into C names. Should make
* this more fine grained and distribute the functionality to the * this more fine grained and distribute the functionality to the
* generators. * 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) * @author Sucheta Dambalkar(Revised)
*/ */
class Mangle { public class Mangle {
public static class Type { public static class Type {
public static final int CLASS = 1; public static final int CLASS = 1;
public static final int FIELDSTUB = 2; public static final int FIELDSTUB = 2;
public static final int FIELD = 3; public static final int FIELD = 3;
public static final int JNI = 4; public static final int JNI = 4;
public static final int SIGNATURE = 5; public static final int SIGNATURE = 5;
public static final int METHOD_JDK_1 = 6; public static final int METHOD_JDK_1 = 6;
@ -49,8 +57,15 @@ class Mangle {
public static final int METHOD_JNI_LONG = 8; 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); StringBuffer result = new StringBuffer(100);
int length = name.length(); int length = name.length();
@ -98,15 +113,15 @@ class Mangle {
return result.toString(); return result.toString();
} }
public static String mangleMethod(MethodDoc method, RootDoc root, ClassDoc clazz, public String mangleMethod(ExecutableElement method, TypeElement clazz,
int mtype) { int mtype) {
StringBuffer result = new StringBuffer(100); StringBuffer result = new StringBuffer(100);
result.append("Java_"); result.append("Java_");
if (mtype == Mangle.Type.METHOD_JDK_1) { 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('_');
result.append(mangle(method.name(), result.append(mangle(method.getSimpleName(),
Mangle.Type.FIELD)); Mangle.Type.FIELD));
result.append("_stub"); result.append("_stub");
return result.toString(); return result.toString();
@ -115,13 +130,13 @@ class Mangle {
/* JNI */ /* JNI */
result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI)); result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
result.append('_'); result.append('_');
result.append(mangle(method.name(), result.append(mangle(method.getSimpleName(),
Mangle.Type.JNI)); Mangle.Type.JNI));
if (mtype == Mangle.Type.METHOD_JNI_LONG) { if (mtype == Mangle.Type.METHOD_JNI_LONG) {
result.append("__"); result.append("__");
String typesig = method.signature(); String typesig = signature(method);
TypeSignature newTypeSig = new TypeSignature(root); TypeSignature newTypeSig = new TypeSignature(elems);
String sig = newTypeSig.getTypeSignature(typesig, method.returnType()); String sig = newTypeSig.getTypeSignature(typesig, method.getReturnType());
sig = sig.substring(1); sig = sig.substring(1);
sig = sig.substring(0, sig.lastIndexOf(')')); sig = sig.substring(0, sig.lastIndexOf(')'));
sig = sig.replace('/', '.'); sig = sig.replace('/', '.');
@ -131,15 +146,11 @@ class Mangle {
return result.toString(); return result.toString();
} }
//where //where
private static String getInnerQualifiedName(ClassDoc clazz) { private String getInnerQualifiedName(TypeElement clazz) {
ClassDoc encl = clazz.containingClass(); return elems.getBinaryName(clazz).toString();
if (encl == null)
return clazz.qualifiedName();
else
return getInnerQualifiedName(encl) + '$' + clazz.simpleTypeName();
} }
public static final String mangleChar(char ch) { public final String mangleChar(char ch) {
String s = Integer.toHexString(ch); String s = Integer.toHexString(ch);
int nzeros = 5 - s.length(); int nzeros = 5 - s.length();
char[] result = new char[6]; char[] result = new char[6];
@ -151,6 +162,19 @@ class Mangle {
return new String(result); 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. */ /* Warning: Intentional ASCII operation. */
private static final boolean isalnum(char ch) { private static final boolean isalnum(char ch) {
return ch <= 0x7f && /* quick test */ 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,19 +26,34 @@
package com.sun.tools.javah; package com.sun.tools.javah;
import com.sun.javadoc.*;
import java.io.*;
import java.util.*; 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. * 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 * @author Sucheta Dambalkar
*/ */
public class TypeSignature{ public class TypeSignature{
RootDoc root = null; Elements elems;
/* Signature Characters */ /* Signature Characters */
@ -56,8 +71,8 @@ public class TypeSignature{
public TypeSignature(RootDoc root){ public TypeSignature(Elements elems){
this.root = root; this.elems = elems;
} }
/* /*
@ -70,16 +85,15 @@ public class TypeSignature{
/* /*
* Returns the type signature of a method according to JVM specs * 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 signature = null; //Java type signature.
String typeSignature = null; //Internal 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 paramsig = null; //Java parameter signature.
String paramJVMSig = null; //Internal parameter signature. String paramJVMSig = null; //Internal parameter signature.
String returnSig = null; //Java return type signature. String returnSig = null; //Java return type signature.
String returnJVMType = null; //Internal return type signature. String returnJVMType = null; //Internal return type signature.
String dimension = null; //Array dimension. int dimensions = 0; //Array dimension.
int startIndex = -1; int startIndex = -1;
int endIndex = -1; int endIndex = -1;
@ -87,28 +101,27 @@ public class TypeSignature{
int i = 0; int i = 0;
// Gets the actual java signature without parentheses. // Gets the actual java signature without parentheses.
if(javasignature != null){ if (javasignature != null) {
startIndex = javasignature.indexOf("("); startIndex = javasignature.indexOf("(");
endIndex = javasignature.indexOf(")"); endIndex = javasignature.indexOf(")");
} }
if(((startIndex != -1) && (endIndex != -1)) if (((startIndex != -1) && (endIndex != -1))
&&(startIndex+1 < javasignature.length()) &&(startIndex+1 < javasignature.length())
&&(endIndex < javasignature.length())) { &&(endIndex < javasignature.length())) {
signature = javasignature.substring(startIndex+1, endIndex); signature = javasignature.substring(startIndex+1, endIndex);
} }
// Separates parameters. // Separates parameters.
if(signature != null){ if (signature != null) {
if(signature.indexOf(",") != -1){ if (signature.indexOf(",") != -1) {
st = new StringTokenizer(signature, ","); st = new StringTokenizer(signature, ",");
if(st != null){ if (st != null) {
while (st.hasMoreTokens()) { while (st.hasMoreTokens()) {
params.add(st.nextToken()); params.add(st.nextToken());
} }
} }
}else { } else {
params.add(signature); params.add(signature);
} }
} }
@ -117,10 +130,10 @@ public class TypeSignature{
typeSignature = "("; typeSignature = "(";
// Gets indivisual internal parameter signature. // Gets indivisual internal parameter signature.
while(params.isEmpty() != true){ while (params.isEmpty() != true) {
paramsig =((String)params.remove(i)).trim(); paramsig = params.remove(i).trim();
paramJVMSig = getParamJVMSignature(paramsig); paramJVMSig = getParamJVMSignature(paramsig);
if(paramJVMSig != null){ if (paramJVMSig != null) {
typeSignature += paramJVMSig; typeSignature += paramJVMSig;
} }
} }
@ -130,36 +143,30 @@ public class TypeSignature{
// Get internal return type signature. // Get internal return type signature.
returnJVMType = ""; returnJVMType = "";
if(returnType != null){ if (returnType != null) {
dimension = returnType.dimension(); dimensions = dimensions(returnType);
} }
if(dimension != null){ //Gets array dimension of return type.
while (dimensions-- > 0) {
//Gets array dimension of return type. returnJVMType += "[";
while(dimension.indexOf("[]") != -1){
returnJVMType += "[";
int stindex = dimension.indexOf("]") + 1;
if(stindex <= dimension.length()){
dimension = dimension.substring(stindex);
}else dimension = "";
}
} }
if(returnType != null){ if (returnType != null) {
returnSig = returnType.qualifiedTypeName(); returnSig = qualifiedTypeName(returnType);
returnJVMType += getComponentType(returnSig); returnJVMType += getComponentType(returnSig);
}else { } else {
System.out.println("Invalid return type."); System.out.println("Invalid return type.");
} }
typeSignature += returnJVMType; typeSignature += returnJVMType;
return typeSignature; return typeSignature;
} }
/* /*
* Returns internal signature of a parameter. * Returns internal signature of a parameter.
*/ */
private String getParamJVMSignature(String paramsig){ private String getParamJVMSignature(String paramsig) {
String paramJVMSig = ""; String paramJVMSig = "";
String componentType =""; String componentType ="";
@ -206,12 +213,13 @@ public class TypeSignature{
else if(componentType.equals("double")) JVMSig += SIG_DOUBLE ; else if(componentType.equals("double")) JVMSig += SIG_DOUBLE ;
else { else {
if(!componentType.equals("")){ if(!componentType.equals("")){
ClassDoc classNameDoc = root.classNamed(componentType); TypeElement classNameDoc = elems.getTypeElement(componentType);
if(classNameDoc == null){ if(classNameDoc == null){
System.out.println("Invalid class type"); System.out.println("Invalid class type for " + componentType);
new Exception().printStackTrace();
}else { }else {
String classname = classNameDoc.qualifiedName(); String classname = classNameDoc.getQualifiedName().toString();
String newclassname = classname.replace('.', '/'); String newclassname = classname.replace('.', '/');
JVMSig += "L"; JVMSig += "L";
JVMSig += newclassname; JVMSig += newclassname;
@ -222,4 +230,43 @@ public class TypeSignature{
} }
return JVMSig; 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,12 +26,15 @@
package com.sun.tools.javah; package com.sun.tools.javah;
import java.io.File; import java.io.PrintWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ResourceBundle;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.MissingResourceException; 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. * Messages, verbose and error handling support.
@ -41,42 +44,70 @@ import java.util.MissingResourceException;
* bug -- Bug has occurred in javah * bug -- Bug has occurred in javah
* fatal -- We can't even find resources, so bail fast, don't localize * 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 { 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. * Help for verbosity.
*/ */
public static boolean verbose = false; public boolean verbose = false;
public static void log(String s) { public PrintWriter log;
System.out.println(s); 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. * Help for loading localized messages.
*/ */
private static ResourceBundle m; private ResourceBundle m;
private static void initMessages() { private void initMessages() throws Exit {
try { try {
m=ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n"); m = ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n");
} catch (MissingResourceException mre) { } catch (MissingResourceException mre) {
fatal("Error loading resources. Please file a bug report.", mre); fatal("Error loading resources. Please file a bug report.", mre);
} }
} }
public static String getText(String key) { private String getText(String key, Object... args) throws Exit {
return getText(key, null, null);
}
private static String getText(String key, String a1, String a2){
if (m == null) if (m == null)
initMessages(); initMessages();
try { try {
return MessageFormat.format(m.getString(key), return MessageFormat.format(m.getString(key), args);
new Object[] { a1, a2 });
} catch (MissingResourceException e) { } catch (MissingResourceException e) {
fatal("Key " + key + " not found in resources.", e); fatal("Key " + key + " not found in resources.", e);
} }
@ -86,107 +117,74 @@ public class Util {
/* /*
* Usage message. * Usage message.
*/ */
public static void usage(int exitValue) { public void usage() throws Exit {
if (exitValue == 0) { log.println(getText("usage"));
System.out.println(getText("usage"));
} else {
System.err.println(getText("usage"));
}
System.exit(exitValue);
} }
public static void version() { public void version() throws Exit {
System.out.println(getText("javah.version", log.println(getText("javah.version",
System.getProperty("java.version"), null)); System.getProperty("java.version"), null));
System.exit(0);
} }
/* /*
* Failure modes. * Failure modes.
*/ */
public static void bug(String key) { public void bug(String key) throws Exit {
bug(key, null); bug(key, null);
} }
public static void bug(String key, Exception e) { public void bug(String key, Exception e) throws Exit {
if (e != null) dl.report(createDiagnostic(Diagnostic.Kind.ERROR, key));
e.printStackTrace(); dl.report(createDiagnostic(Diagnostic.Kind.NOTE, "bug.report"));
System.err.println(getText(key)); throw new Exit(11, e);
System.err.println(getText("bug.report"));
System.exit(11);
} }
public static void error(String key) { public void error(String key, Object... args) throws Exit {
error(key, null); dl.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));
throw new Exit(15);
} }
public static void error(String key, String a1) { private void fatal(String msg) throws Exit {
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) {
fatal(msg, null); fatal(msg, null);
} }
private static void fatal(String msg, Exception e) { private void fatal(String msg, Exception e) throws Exit {
if (e != null) { dl.report(createDiagnostic(Diagnostic.Kind.ERROR, "", msg));
e.printStackTrace(); throw new Exit(10, e);
}
System.err.println(msg);
System.exit(10);
} }
/* private Diagnostic<JavaFileObject> createDiagnostic(
* Support for platform specific things in javah, such as pragma final Diagnostic.Kind kind, final String code, final Object... args) {
* directives, exported symbols etc. return new Diagnostic<JavaFileObject>() {
*/ public String getCode() {
static private ResourceBundle platform = null; return code;
}
/* public long getColumnNumber() {
* Set when platform has been initialized. return Diagnostic.NOPOS;
*/ }
static private boolean platformInit = false; public long getEndPosition() {
return Diagnostic.NOPOS;
static String getPlatformString(String key) { }
if (!platformInit) { public Kind getKind() {
initPlatform(); return kind;
platformInit = true; }
} public long getLineNumber() {
if (platform == null) return Diagnostic.NOPOS;
return null; }
try { public String getMessage(Locale locale) {
return platform.getString(key); if (code.length() == 0)
} catch (MissingResourceException mre) { return (String) args[0];
return null; return getText(code, args); // FIXME locale
} }
} public long getPosition() {
return Diagnostic.NOPOS;
private static void initPlatform() { }
String os = System.getProperty("os.name"); public JavaFileObject getSource() {
if (os.startsWith("Windows")) { return null;
os = "win32"; }
} else if (os.indexOf("Linux") >= 0) { public long getStartPosition() {
os = "Linux"; return Diagnostic.NOPOS;
} }
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

@ -27,41 +27,41 @@
# User errors, command line errors. # User errors, command line errors.
# #
cant.create.dir=\ cant.create.dir=\
The directory {0} could not be create for output. The directory {0} could not be create for output.
at.args.cant.read=\ at.args.cant.read=\
Can''t read command line arguments from file {1}. Can''t read command line arguments from file {1}.
at.args.io.exception=\ at.args.io.exception=\
The following I/O problem was encountered when processing an @ \ The following I/O problem was encountered when processing an @ \
argument on the command line: {0}. argument on the command line: {0}.
old.jni.mixed=\ old.jni.mixed=\
Can''t mix options -jni and -old. Try -help. Can''t mix options -jni and -old. Try -help.
old.llni.mixed=\ old.llni.mixed=\
Can''t mix options -old and -llni. Try -help. Can''t mix options -old and -llni. Try -help.
old.not.supported=\ old.not.supported=\
Option -old not supported by this version of javah. Option -old not supported by this version of javah.
invalid.method.signature=\ invalid.method.signature=\
Invalid method signature: {0} Invalid method signature: {0}
jni.llni.mixed=\ jni.llni.mixed=\
Can''t mix options -jni and -llni. Try -help. Can''t mix options -jni and -llni. Try -help.
jni.no.stubs=\ jni.no.stubs=\
JNI does not require stubs, please refer to the JNI documentation. JNI does not require stubs, please refer to the JNI documentation.
dir.file.mixed=\ dir.file.mixed=\
Can''t mix options -d and -o. Try -help. Can''t mix options -d and -o. Try -help.
no.classes.specified=\ no.classes.specified=\
No classes were specified on the command line. Try -help. No classes were specified on the command line. Try -help.
no.outputfile.specified=\ no.outputfile.specified=\
No outputfile was specified on the command line. Try -help. No outputfile was specified on the command line. Try -help.
no.outputdir.specified=\ no.outputdir.specified=\
No output directory was specified on the command line. Try -help. No output directory was specified on the command line. Try -help.
no.classpath.specified=\ no.classpath.specified=\
No classpath was specified on the command line. Try -help. No classpath was specified on the command line. Try -help.
no.bootclasspath.specified=\ no.bootclasspath.specified=\
No bootclasspath was specified on the command line. Try -help. No bootclasspath was specified on the command line. Try -help.
unknown.option=\ unknown.option=\
{0} is an illegal argument\n {0} is an illegal argument\n
tracing.not.supported=\ tracing.not.supported=\
Warning: Tracing is no longer supported. Instead, use\ Warning: Tracing is no longer supported. Instead, use\
-verbose:jni option of the virtual machine. -verbose:jni option of the virtual machine.
# #
# Usage message. # Usage message.
@ -79,11 +79,37 @@ where [options] include:\n\
-jni Generate JNI-style header file (default)\n\t\ -jni Generate JNI-style header file (default)\n\t\
-version Print version information\n\t\ -version Print version information\n\t\
-verbose Enable verbose output\n\t\ -verbose Enable verbose output\n\t\
-force Always write output files\n\ -force Always write output files\n\
\n\ \n\
<classes> are specified with their fully qualified names (for\n\ <classes> are specified with their fully qualified names (for\n\
instance, java.lang.Object).\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. # Version string.
# #
@ -93,26 +119,35 @@ javah.version=javah version "{0}"
# These should have better diagnostics. # These should have better diagnostics.
# #
super.class.not.found=\ super.class.not.found=\
A required super class {0} could not be found. A required super class {0} could not be found.
class.not.found=\ class.not.found=\
Class {0} could not be found. Class {0} could not be found.
io.exception=\ io.exception=\
Can''t recover from an I/O error with the following message: \ Can''t recover from an I/O error with the following message: \
{0}. {0}.
# #
# Problems in the guts of javah. # Problems in the guts of javah.
# #
encoding.iso8859_1.not.found=\ encoding.iso8859_1.not.found=\
ISO8859_1 converter was not found for output. This is \ ISO8859_1 converter was not found for output. This is \
probably due to an error in the installation installation. probably due to an error in the installation installation.
tried.to.define.non.static=\ tried.to.define.non.static=\
Tried to generate #define for non-static field. Tried to generate #define for non-static field.
jni.unknown.type=\ jni.unknown.type=\
An unknown type encountered (JNI). An unknown type encountered (JNI).
unknown.array.type=\ unknown.array.type=\
An unknown array type encountered when generating old style headers. An unknown array type encountered when generating old style headers.
unknown.type.for.field=\ unknown.type.for.field=\
An unknown type encountered when generating old style headers. An unknown type encountered when generating old style headers.
unknown.type.in.method.signature=\ unknown.type.in.method.signature=\
An unknown type eccountered when generating old style stubs. 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 DiagnosticListener
* @see Diagnostic * @see Diagnostic
* @see JavaFileManager * @see JavaFileManager
* @since 1.6 * @since 1.7
* *
* <p><b>This is NOT part of any API supported by Sun Microsystems. If * <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. * 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 ParamClassTest.class MissingParamClassException.class ParamClassTest.h
rm -f ${TMP1} rm -f ${TMP1}
cp ${TESTSRC}${FS}ParamClassTest.java . "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java" "${TESTSRC}${FS}MissingParamClassException.java"
cp ${TESTSRC}${FS}MissingParamClassException.java .
"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java"
# Before running javah remove dependent class file # Before running javah remove dependent class file
rm -f MissingParamClassException.class rm -f MissingParamClassException.class
@ -88,15 +85,12 @@ rm -f MissingParamClassException.class
"${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1} "${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1}
if [ -f $GENERATED_HEADER_FILE ]; then if [ -f $GENERATED_HEADER_FILE ]; then
echo "Failed" echo "1-- Failed: $GENERATED_HEADER_FILE found"
exit 1 rc=1
fi fi
if [ ! -f ${TMP1} ]; then if [ ! -s ${TMP1} ]; then
echo "Failed" echo "1-- Failed: ${TMP1} is empty"
exit 1 rc=1
else
echo "Passed"
exit 0
fi fi
# Clean out work dir # Clean out work dir
@ -104,7 +98,9 @@ rm -f MissingParamClassException.class ParamClassTest.class
rm -f $GENERATED_HEADER_FILE $TMP1 rm -f $GENERATED_HEADER_FILE $TMP1
# Re-compile everything # 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 # Before re-run of javah remove dependent class file Param.class
rm -f Param.class rm -f Param.class
@ -112,13 +108,17 @@ rm -f Param.class
"${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1} "${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1}
if [ -f $GENERATED_HEADER_FILE ]; then if [ -f $GENERATED_HEADER_FILE ]; then
echo "Failed" echo "2-- Failed: $GENERATED_HEADER_FILE found"
exit 1 rc=1
fi fi
if [ ! -f ${TMP1} ]; then if [ ! -s ${TMP1} ]; then
echo "Failed" echo "2-- Failed: ${TMP1} is empty"
exit 1 rc=1
fi
if [ "$rc" = "" ]; then
echo Passed
else else
echo "Passed" echo Failed
exit 0 exit 1
fi 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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # 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 # under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this # published by the Free Software Foundation.
# 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 # This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@ -23,5 +22,22 @@
# have any questions. # have any questions.
# #
pack.pragma.start=\#pragma pack(4)\n jdk=${1:-/opt/jdk/1.6.0}
pack.pragma.end=\#pragma pack()\n 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.