--- a/langtools/src/share/classes/com/sun/tools/javah/JNI.java Tue Oct 12 13:15:46 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javah/JNI.java Tue Oct 12 13:19:47 2010 -0700
@@ -59,72 +59,76 @@
}
public void write(OutputStream o, TypeElement clazz) throws Util.Exit {
- String cname = mangler.mangle(clazz.getQualifiedName(), Mangle.Type.CLASS);
- PrintWriter pw = wrapWriter(o);
- pw.println(guardBegin(cname));
- pw.println(cppGuardBegin());
+ try {
+ String cname = mangler.mangle(clazz.getQualifiedName(), Mangle.Type.CLASS);
+ PrintWriter pw = wrapWriter(o);
+ pw.println(guardBegin(cname));
+ pw.println(cppGuardBegin());
- /* Write statics. */
- List<VariableElement> classfields = getAllFields(clazz);
+ /* Write statics. */
+ List<VariableElement> classfields = getAllFields(clazz);
- for (VariableElement v: classfields) {
- if (!v.getModifiers().contains(Modifier.STATIC))
- continue;
- String s = null;
- s = defineForStatic(clazz, v);
- if (s != null) {
- pw.println(s);
+ for (VariableElement v: classfields) {
+ if (!v.getModifiers().contains(Modifier.STATIC))
+ continue;
+ String s = null;
+ s = defineForStatic(clazz, v);
+ if (s != null) {
+ pw.println(s);
+ }
}
- }
- /* Write methods. */
- List<ExecutableElement> classmethods = ElementFilter.methodsIn(clazz.getEnclosedElements());
- for (ExecutableElement md: classmethods) {
- if(md.getModifiers().contains(Modifier.NATIVE)){
- TypeMirror mtr = types.erasure(md.getReturnType());
- String sig = signature(md);
- TypeSignature newtypesig = new TypeSignature(elems);
- CharSequence methodName = md.getSimpleName();
- boolean longName = false;
- for (ExecutableElement md2: classmethods) {
- if ((md2 != md)
- && (methodName.equals(md2.getSimpleName()))
- && (md2.getModifiers().contains(Modifier.NATIVE)))
- longName = true;
+ /* Write methods. */
+ List<ExecutableElement> classmethods = ElementFilter.methodsIn(clazz.getEnclosedElements());
+ for (ExecutableElement md: classmethods) {
+ if(md.getModifiers().contains(Modifier.NATIVE)){
+ TypeMirror mtr = types.erasure(md.getReturnType());
+ String sig = signature(md);
+ TypeSignature newtypesig = new TypeSignature(elems);
+ CharSequence methodName = md.getSimpleName();
+ boolean longName = false;
+ for (ExecutableElement md2: classmethods) {
+ if ((md2 != md)
+ && (methodName.equals(md2.getSimpleName()))
+ && (md2.getModifiers().contains(Modifier.NATIVE)))
+ longName = true;
+ }
+ pw.println("/*");
+ pw.println(" * Class: " + cname);
+ pw.println(" * Method: " +
+ mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
+ pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr));
+ pw.println(" */");
+ pw.println("JNIEXPORT " + jniType(mtr) +
+ " JNICALL " +
+ mangler.mangleMethod(md, clazz,
+ (longName) ?
+ Mangle.Type.METHOD_JNI_LONG :
+ Mangle.Type.METHOD_JNI_SHORT));
+ pw.print(" (JNIEnv *, ");
+ List<? extends VariableElement> paramargs = md.getParameters();
+ List<TypeMirror> args = new ArrayList<TypeMirror>();
+ for (VariableElement p: paramargs) {
+ args.add(types.erasure(p.asType()));
+ }
+ if (md.getModifiers().contains(Modifier.STATIC))
+ pw.print("jclass");
+ else
+ pw.print("jobject");
+
+ for (TypeMirror arg: args) {
+ pw.print(", ");
+ pw.print(jniType(arg));
+ }
+ pw.println(");" + lineSep);
}
- pw.println("/*");
- pw.println(" * Class: " + cname);
- pw.println(" * Method: " +
- mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
- pw.println(" * Signature: " + newtypesig.getTypeSignature(sig, mtr));
- pw.println(" */");
- pw.println("JNIEXPORT " + jniType(mtr) +
- " JNICALL " +
- mangler.mangleMethod(md, clazz,
- (longName) ?
- Mangle.Type.METHOD_JNI_LONG :
- Mangle.Type.METHOD_JNI_SHORT));
- pw.print(" (JNIEnv *, ");
- List<? extends VariableElement> paramargs = md.getParameters();
- List<TypeMirror> args = new ArrayList<TypeMirror>();
- for (VariableElement p: paramargs) {
- args.add(types.erasure(p.asType()));
- }
- if (md.getModifiers().contains(Modifier.STATIC))
- pw.print("jclass");
- else
- pw.print("jobject");
-
- for (TypeMirror arg: args) {
- pw.print(", ");
- pw.print(jniType(arg));
- }
- pw.println(");" + lineSep);
}
+ pw.println(cppGuardEnd());
+ pw.println(guardEnd(cname));
+ } catch (TypeSignature.SignatureException e) {
+ util.error("jni.sigerror", e.getMessage());
}
- pw.println(cppGuardEnd());
- pw.println(guardEnd(cname));
}
--- a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java Tue Oct 12 13:15:46 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java Tue Oct 12 13:19:47 2010 -0700
@@ -46,9 +46,9 @@
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
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;
@@ -71,6 +71,9 @@
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
+import static javax.tools.Diagnostic.Kind.*;
+
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
/**
* Javah generates support files for native methods.
@@ -233,6 +236,15 @@
task.doubleAlign = true;
}
},
+
+ new HiddenOption(false) {
+ boolean matches(String opt) {
+ return opt.startsWith("-XD");
+ }
+ void process(JavahTask task, String opt, String arg) {
+ task.javac_extras.add(opt);
+ }
+ },
};
JavahTask() {
@@ -326,6 +338,8 @@
} catch (InternalError e) {
diagnosticListener.report(createDiagnostic("err.internal.error", e.getMessage()));
return 1;
+ } catch (Util.Exit e) {
+ return e.exitValue;
} finally {
log.flush();
}
@@ -475,7 +489,9 @@
((JavahFileManager) fileManager).setIgnoreSymbolFile(true);
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
- List<String> opts = Arrays.asList("-proc:only");
+ List<String> opts = new ArrayList<String>();
+ opts.add("-proc:only");
+ opts.addAll(javac_extras);
CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, internalize(classes), null);
JavahProcessor p = new JavahProcessor(g);
t.setProcessors(Collections.singleton(p));
@@ -642,6 +658,7 @@
boolean doubleAlign;
boolean force;
boolean old;
+ Set<String> javac_extras = new LinkedHashSet<String>();
PrintWriter log;
JavaFileManager fileManager;
@@ -652,30 +669,45 @@
private static final String progname = "javah";
@SupportedAnnotationTypes("*")
- @SupportedSourceVersion(SourceVersion.RELEASE_7)
class JavahProcessor extends AbstractProcessor {
+ private Messager messager;
+
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);
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ // since this is co-bundled with javac, we can assume it supports
+ // the latest source version
+ return SourceVersion.latest();
+ }
+
+ @Override
+ public void init(ProcessingEnvironment pEnv) {
+ super.init(pEnv);
+ messager = processingEnv.getMessager();
+ }
- try {
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ try {
+ Set<TypeElement> classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements()));
+ if (classes.size() > 0) {
+ checkMethodParameters(classes);
+ g.setProcessingEnvironment(processingEnv);
+ g.setClasses(classes);
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;
}
+ } catch (CompletionFailure cf) {
+ messager.printMessage(ERROR, getMessage("class.not.found", cf.sym.getQualifiedName().toString()));
+ } catch (ClassNotFoundException cnfe) {
+ messager.printMessage(ERROR, getMessage("class.not.found", cnfe.getMessage()));
+ } catch (IOException ioe) {
+ messager.printMessage(ERROR, getMessage("io.exception", ioe.getMessage()));
+ } catch (Util.Exit e) {
+ exit = e;
}
+
return true;
}
--- a/langtools/src/share/classes/com/sun/tools/javah/LLNI.java Tue Oct 12 13:15:46 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javah/LLNI.java Tue Oct 12 13:19:47 2010 -0700
@@ -74,16 +74,21 @@
}
protected void write(OutputStream o, TypeElement clazz) throws Util.Exit {
- String cname = mangleClassName(clazz.getQualifiedName().toString());
- PrintWriter pw = wrapWriter(o);
- fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
- methods = ElementFilter.methodsIn(clazz.getEnclosedElements());
- generateDeclsForClass(pw, clazz, cname);
- // FIXME check if errors occurred on the PrintWriter and throw exception if so
+ try {
+ String cname = mangleClassName(clazz.getQualifiedName().toString());
+ PrintWriter pw = wrapWriter(o);
+ fields = ElementFilter.fieldsIn(clazz.getEnclosedElements());
+ methods = ElementFilter.methodsIn(clazz.getEnclosedElements());
+ generateDeclsForClass(pw, clazz, cname);
+ // FIXME check if errors occurred on the PrintWriter and throw exception if so
+ } catch (TypeSignature.SignatureException e) {
+ util.error("llni.sigerror", e.getMessage());
+ }
}
protected void generateDeclsForClass(PrintWriter pw,
- TypeElement clazz, String cname) throws Util.Exit {
+ TypeElement clazz, String cname)
+ throws TypeSignature.SignatureException, Util.Exit {
doneHandleTypes = new HashSet<String>();
/* The following handle types are predefined in "typedefs.h". Suppress
inclusion in the output by generating them "into the blue" here. */
@@ -127,7 +132,8 @@
.replace(innerDelim, '_');
}
- protected void forwardDecls(PrintWriter pw, TypeElement clazz) {
+ protected void forwardDecls(PrintWriter pw, TypeElement clazz)
+ throws TypeSignature.SignatureException {
TypeElement object = elems.getTypeElement("java.lang.Object");
if (clazz.equals(object))
return;
@@ -403,7 +409,7 @@
protected void methodSectionForClass(PrintWriter pw,
TypeElement clazz, String cname)
- throws Util.Exit {
+ throws TypeSignature.SignatureException, Util.Exit {
String methods = methodDecls(clazz, cname);
if (methods.length() != 0) {
@@ -418,7 +424,8 @@
}
}
- protected String methodDecls(TypeElement clazz, String cname) throws Util.Exit {
+ protected String methodDecls(TypeElement clazz, String cname)
+ throws TypeSignature.SignatureException, Util.Exit {
String res = "";
for (ExecutableElement method: methods) {
@@ -430,7 +437,7 @@
protected String methodDecl(ExecutableElement method,
TypeElement clazz, String cname)
- throws Util.Exit {
+ throws TypeSignature.SignatureException, Util.Exit {
String res = null;
TypeMirror retType = types.erasure(method.getReturnType());
@@ -474,7 +481,8 @@
}
protected final String jniMethodName(ExecutableElement method, String cname,
- boolean longName) {
+ boolean longName)
+ throws TypeSignature.SignatureException {
String res = "Java_" + cname + "_" + method.getSimpleName();
if (longName) {
--- a/langtools/src/share/classes/com/sun/tools/javah/Mangle.java Tue Oct 12 13:15:46 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javah/Mangle.java Tue Oct 12 13:19:47 2010 -0700
@@ -114,7 +114,7 @@
}
public String mangleMethod(ExecutableElement method, TypeElement clazz,
- int mtype) {
+ int mtype) throws TypeSignature.SignatureException {
StringBuffer result = new StringBuffer(100);
result.append("Java_");
--- a/langtools/src/share/classes/com/sun/tools/javah/TypeSignature.java Tue Oct 12 13:15:46 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javah/TypeSignature.java Tue Oct 12 13:19:47 2010 -0700
@@ -51,7 +51,13 @@
* @author Sucheta Dambalkar
*/
-public class TypeSignature{
+public class TypeSignature {
+ static class SignatureException extends Exception {
+ private static final long serialVersionUID = 1L;
+ SignatureException(String reason) {
+ super(reason);
+ }
+ }
Elements elems;
@@ -78,14 +84,15 @@
/*
* Returns the type signature of a field according to JVM specs
*/
- public String getTypeSignature(String javasignature){
+ public String getTypeSignature(String javasignature) throws SignatureException {
return getParamJVMSignature(javasignature);
}
/*
* Returns the type signature of a method according to JVM specs
*/
- public String getTypeSignature(String javasignature, TypeMirror returnType){
+ public String getTypeSignature(String javasignature, TypeMirror returnType)
+ throws SignatureException {
String signature = null; //Java type signature.
String typeSignature = null; //Internal type signature.
List<String> params = new ArrayList<String>(); //List of parameters.
@@ -166,7 +173,7 @@
/*
* Returns internal signature of a parameter.
*/
- private String getParamJVMSignature(String paramsig) {
+ private String getParamJVMSignature(String paramsig) throws SignatureException {
String paramJVMSig = "";
String componentType ="";
@@ -197,7 +204,7 @@
/*
* Returns internal signature of a component.
*/
- private String getComponentType(String componentType){
+ private String getComponentType(String componentType) throws SignatureException {
String JVMSig = "";
@@ -216,8 +223,7 @@
TypeElement classNameDoc = elems.getTypeElement(componentType);
if(classNameDoc == null){
- System.out.println("Invalid class type for " + componentType);
- new Exception().printStackTrace();
+ throw new SignatureException(componentType);
}else {
String classname = classNameDoc.getQualifiedName().toString();
String newclassname = classname.replace('.', '/');
--- a/langtools/src/share/classes/com/sun/tools/javah/resources/l10n.properties Tue Oct 12 13:15:46 2010 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javah/resources/l10n.properties Tue Oct 12 13:19:47 2010 -0700
@@ -45,6 +45,8 @@
Can''t mix options -jni and -llni. Try -help.
jni.no.stubs=\
JNI does not require stubs, please refer to the JNI documentation.
+jni.sigerror=\
+ Cannot determine signature for {0}
dir.file.mixed=\
Can''t mix options -d and -o. Try -help.
no.classes.specified=\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javah/4942232/ParamClassTest.java Tue Oct 12 13:19:47 2010 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class ParamClassTest {
+ static {
+ System.loadLibrary("Test");
+ }
+
+ public native void method(Param s);
+
+ public static void main(String[] a) {
+ }
+}
+
+class Param {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javah/4942232/Test.java Tue Oct 12 13:19:47 2010 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4942232
+ * @summary missing param class processes without error
+ * @build ParamClassTest Test
+ * @run main Test
+ */
+
+import java.io.*;
+import java.util.*;
+
+public class Test {
+ public static void main(String... args) throws Exception {
+ new Test().run();
+ }
+
+ void run() throws Exception {
+ File testSrc = new File(System.getProperty("test.src"));
+ File testClasses = new File(System.getProperty("test.classes"));
+
+ // standard use of javah on valid class file
+ String[] test1Args = {
+ "-d", mkdir("test1/out").getPath(),
+ "-classpath", testClasses.getPath(),
+ "ParamClassTest"
+ };
+ test(test1Args, 0);
+
+ // extended use of javah on valid source file
+ String[] test2Args = {
+ "-d", mkdir("test2/out").getPath(),
+ "-classpath", testSrc.getPath(),
+ "ParamClassTest"
+ };
+ test(test2Args, 0);
+
+ // javah on class file with missing referents
+ File test3Classes = mkdir("test3/classes");
+ copy(new File(testClasses, "ParamClassTest.class"), test3Classes);
+ String[] test3Args = {
+ "-d", mkdir("test3/out").getPath(),
+ "-classpath", test3Classes.getPath(),
+ "ParamClassTest"
+ };
+ test(test3Args, 1);
+
+ // javah on source file with missing referents
+ File test4Src = mkdir("test4/src");
+ String paramClassTestSrc = readFile(new File(testSrc, "ParamClassTest.java"));
+ writeFile(new File(test4Src, "ParamClassTest.java"),
+ paramClassTestSrc.replaceAll("class Param \\{\\s+\\}", ""));
+ String[] test4Args = {
+ "-d", mkdir("test4/out").getPath(),
+ "-classpath", test4Src.getPath(),
+ "ParamClassTest"
+ };
+ test(test4Args, 15);
+
+ if (errors > 0)
+ throw new Exception(errors + " errors occurred");
+ }
+
+ void test(String[] args, int expect) {
+ System.err.println("test: " + Arrays.asList(args));
+ int rc = javah(args);
+ if (rc != expect)
+ error("Unexpected return code: " + rc + "; expected: " + expect);
+ }
+
+ int javah(String... args) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ int rc = com.sun.tools.javah.Main.run(args, pw);
+ pw.close();
+ String out = sw.toString();
+ if (!out.isEmpty())
+ System.err.println(out);
+ return rc;
+ }
+
+ File mkdir(String path) {
+ File f = new File(path);
+ f.mkdirs();
+ return f;
+ }
+
+ void copy(File from, File to) throws IOException {
+ if (to.isDirectory())
+ to = new File(to, from.getName());
+ try (DataInputStream in = new DataInputStream(new FileInputStream(from));
+ FileOutputStream out = new FileOutputStream(to)) {
+ byte[] buf = new byte[(int) from.length()];
+ in.readFully(buf);
+ out.write(buf);
+ }
+ }
+
+ String readFile(File f) throws IOException {
+ try (DataInputStream in = new DataInputStream(new FileInputStream(f))) {
+ byte[] buf = new byte[(int) f.length()];
+ in.readFully(buf);
+ return new String(buf);
+ }
+ }
+
+ void writeFile(File f, String body) throws IOException {
+ try (FileWriter out = new FileWriter(f)) {
+ out.write(body);
+ }
+ }
+
+ void error(String msg) {
+ System.err.println(msg);
+ errors++;
+ }
+
+ int errors;
+}