changeset 3209:7766dfafa530

8031545: [javac] refactor and cleanup JNIWriter.java Reviewed-by: jjg
author ksrini
date Sat, 15 Feb 2014 16:37:19 -0800
parents 4c09a8dd09b3
children f50269f5606c e22e769ca395
files src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java test/tools/javac/nativeHeaders/javahComparison/CompareTest.java test/tools/javac/nativeHeaders/javahComparison/TestClass1.java
diffstat 3 files changed, 506 insertions(+), 676 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java	Fri Feb 14 17:28:07 2014 -0800
+++ b/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java	Sat Feb 15 16:37:19 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, 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
@@ -26,30 +26,10 @@
 package com.sun.tools.javac.jvm;
 
 import java.io.IOException;
-import java.io.Writer;
+import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Stack;
-import java.util.StringTokenizer;
-
-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.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.ElementFilter;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.SimpleTypeVisitor8;
-import javax.lang.model.util.Types;
 
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager;
@@ -57,18 +37,22 @@
 
 import com.sun.tools.javac.code.Attribute;
 import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Kinds;
 import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
 import com.sun.tools.javac.model.JavacElements;
-import com.sun.tools.javac.model.JavacTypes;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Options;
+import com.sun.tools.javac.util.Pair;
 
 import static com.sun.tools.javac.main.Option.*;
+import static com.sun.tools.javac.code.Kinds.*;
 
 /** This class provides operations to write native header files for classes.
  *
@@ -83,8 +67,8 @@
     /** Access to files. */
     private final JavaFileManager fileManager;
 
-    JavacElements elements;
-    JavacTypes types;
+    Types      types;
+    Symtab     syms;
 
     /** The log to use for verbose output.
      */
@@ -98,15 +82,9 @@
      */
     private boolean checkAll;
 
-    private Mangle mangler;
-
     private Context context;
 
-    private Symtab syms;
-
-    private String lineSep;
-
-    private final boolean isWindows =
+    private static final boolean isWindows =
         System.getProperty("os.name").startsWith("Windows");
 
     /** Get the ClassWriter instance for this context. */
@@ -129,44 +107,58 @@
         checkAll = options.isSet("javah:full");
 
         this.context = context; // for lazyInit()
-        syms = Symtab.instance(context);
-
-        lineSep = System.getProperty("line.separator");
     }
 
     private void lazyInit() {
-        if (mangler == null) {
-            elements = JavacElements.instance(context);
-            types = JavacTypes.instance(context);
-            mangler = new Mangle(elements, types);
-        }
+        if (types == null)
+            types = Types.instance(context);
+        if (syms == null)
+            syms = Symtab.instance(context);
+
+    }
+
+    static boolean isSynthetic(Symbol s) {
+        return hasFlag(s, Flags.SYNTHETIC);
+    }
+    static boolean isStatic(Symbol s) {
+        return hasFlag(s, Flags.STATIC);
+    }
+    static boolean isFinal(Symbol s) {
+        return hasFlag(s, Flags.FINAL);
+    }
+    static boolean isNative(Symbol s) {
+        return hasFlag(s, Flags.NATIVE);
+    }
+    static private boolean hasFlag(Symbol m, int flag) {
+        return (m.flags() & flag) != 0;
     }
 
     public boolean needsHeader(ClassSymbol c) {
-        if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
+        lazyInit();
+        if (c.isLocal() || isSynthetic(c))
             return false;
-
-        if (checkAll)
-            return needsHeader(c.outermostClass(), true);
-        else
-            return needsHeader(c, false);
+        return (checkAll)
+                ? needsHeader(c.outermostClass(), true)
+                : needsHeader(c, false);
     }
 
     private boolean needsHeader(ClassSymbol c, boolean checkNestedClasses) {
-        if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
+        if (c.isLocal() || isSynthetic(c))
             return false;
 
         for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
-            if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0)
+            Symbol sym = i.sym;
+            if (sym.kind == MTH && isNative(sym))
                 return true;
-            for (Attribute.Compound a: i.sym.getDeclarationAttributes()) {
+            for (Attribute.Compound a: sym.getDeclarationAttributes()) {
                 if (a.type.tsym == syms.nativeHeaderType.tsym)
                     return true;
             }
         }
         if (checkNestedClasses) {
             for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
-                if ((i.sym.kind == Kinds.TYP) && needsHeader(((ClassSymbol) i.sym), true))
+                Symbol sym = i.sym;
+                if ((sym.kind == TYP) && needsHeader(((ClassSymbol) sym), true))
                     return true;
             }
         }
@@ -176,14 +168,12 @@
     /** Emit a class file for a given class.
      *  @param c      The class from which a class file is generated.
      */
-    public FileObject write(ClassSymbol c)
-        throws IOException
-    {
+    public FileObject write(ClassSymbol c) throws IOException {
         String className = c.flatName().toString();
         FileObject outFile
             = fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
                 "", className.replaceAll("[.$]", "_") + ".h", null);
-        Writer out = outFile.openWriter();
+        PrintWriter out = new PrintWriter(outFile.openWriter());
         try {
             write(out, c);
             if (verbose)
@@ -201,201 +191,134 @@
         return outFile; // may be null if write failed
     }
 
-    public void write(Writer out, ClassSymbol sym)
-            throws IOException {
+    public void write(PrintWriter out, ClassSymbol sym) throws IOException {
         lazyInit();
         try {
-            String cname = mangler.mangle(sym.fullname, Mangle.Type.CLASS);
-            println(out, fileTop());
-            println(out, includes());
-            println(out, guardBegin(cname));
-            println(out, cppGuardBegin());
+            String cname = encode(sym.fullname, EncoderType.CLASS);
+            fileTop(out);
+            includes(out);
+            guardBegin(out, cname);
+            cppGuardBegin(out);
 
             writeStatics(out, sym);
             writeMethods(out, sym, cname);
 
-            println(out, cppGuardEnd());
-            println(out, guardEnd(cname));
+            cppGuardEnd(out);
+            guardEnd(out);
         } catch (TypeSignature.SignatureException e) {
             throw new IOException(e);
         }
     }
-
-    protected void writeStatics(Writer out, ClassSymbol sym) throws IOException {
-        List<VariableElement> classfields = getAllFields(sym);
-
-        for (VariableElement v: classfields) {
-            if (!v.getModifiers().contains(Modifier.STATIC))
-                continue;
-            String s = null;
-            s = defineForStatic(sym, v);
-            if (s != null) {
-                println(out, s);
+    protected void writeStatics(PrintWriter out, ClassSymbol sym) throws IOException {
+        List<ClassSymbol> clist = new ArrayList<>();
+        for (ClassSymbol cd = sym; cd != null;
+                cd = (ClassSymbol) cd.getSuperclass().tsym) {
+            clist.add(cd);
+        }
+        /*
+         * list needs to be super-class, base-class1, base-class2 and so on,
+         * so we reverse class hierarchy
+         */
+        Collections.reverse(clist);
+        for (ClassSymbol cd : clist) {
+            for (Symbol i : cd.getEnclosedElements()) {
+                // consider only final, static and fields with ConstantExpressions
+                if (isFinal(i) && i.isStatic() && i.kind == VAR) {
+                    VarSymbol v = (VarSymbol) i;
+                    if (v.getConstantValue() != null) {
+                        Pair<ClassSymbol, VarSymbol> p = new Pair<>(sym, v);
+                        printStaticDefines(out, p);
+                    }
+                }
             }
         }
     }
-
-    /**
-     * Including super class fields.
-     */
-    List<VariableElement> getAllFields(TypeElement subclazz) {
-        List<VariableElement> fields = new ArrayList<>();
-        TypeElement cd = null;
-        Stack<TypeElement> s = new Stack<>();
-
-        cd = subclazz;
-        while (true) {
-            s.push(cd);
-            TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
-            if (c == null)
+    static void printStaticDefines(PrintWriter out, Pair<ClassSymbol, VarSymbol> p) {
+        ClassSymbol cls = p.fst;
+        VarSymbol f = p.snd;
+        Object value = f.getConstantValue();
+        String valueStr = null;
+        switch (f.asType().getKind()) {
+            case BOOLEAN:
+                valueStr = (((Boolean) value) ? "1L" : "0L");
                 break;
-            cd = c;
+            case BYTE: case SHORT: case INT:
+                valueStr = value.toString() + "L";
+                break;
+            case LONG:
+                // Visual C++ supports the i64 suffix, not LL.
+                valueStr = value.toString() + ((isWindows) ? "i64" : "LL");
+                break;
+            case CHAR:
+                Character ch = (Character) value;
+                valueStr = String.valueOf(((int) ch) & 0xffff) + "L";
+                break;
+            case FLOAT:
+                // bug compatible
+                float fv = ((Float) value).floatValue();
+                valueStr = (Float.isInfinite(fv))
+                        ? ((fv < 0) ? "-" : "") + "Inff"
+                        : value.toString() + "f";
+                break;
+            case DOUBLE:
+                // bug compatible
+                double d = ((Double) value).doubleValue();
+                valueStr = (Double.isInfinite(d))
+                        ? ((d < 0) ? "-" : "") + "InfD"
+                        : value.toString();
+                break;
+            default:
+                valueStr = null;
         }
-
-        while (!s.empty()) {
-            cd = s.pop();
-            fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
+        if (valueStr != null) {
+            out.print("#undef ");
+            String cname = encode(cls.getQualifiedName(), EncoderType.CLASS);
+            String fname = encode(f.getSimpleName(), EncoderType.FIELDSTUB);
+            out.println(cname + "_" + fname);
+            out.print("#define " + cname + "_");
+            out.println(fname + " " + valueStr);
         }
-
-        return fields;
     }
-
-    protected String defineForStatic(TypeElement c, VariableElement f) {
-        CharSequence cnamedoc = c.getQualifiedName();
-        CharSequence fnamedoc = f.getSimpleName();
-
-        String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
-        String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
-
-        Assert.check(f.getModifiers().contains(Modifier.STATIC));
-
-        if (f.getModifiers().contains(Modifier.FINAL)) {
-            Object value = null;
-
-            value = f.getConstantValue();
-
-            if (value != null) { /* so it is a ConstantExpression */
-                String constString = null;
-                if ((value instanceof Integer)
-                    || (value instanceof Byte)
-                    || (value instanceof Short)) {
-                    /* covers byte, short, int */
-                    constString = value.toString() + "L";
-                } else if (value instanceof Boolean) {
-                    constString = ((Boolean) value) ? "1L" : "0L";
-                } else if (value instanceof Character) {
-                    Character ch = (Character) value;
-                    constString = String.valueOf(((int) ch) & 0xffff) + "L";
-                } else if (value instanceof Long) {
-                    // Visual C++ supports the i64 suffix, not LL.
-                    if (isWindows)
-                        constString = value.toString() + "i64";
-                    else
-                        constString = value.toString() + "LL";
-                } else if (value instanceof Float) {
-                    /* bug for bug */
-                    float fv = ((Float)value).floatValue();
-                    if (Float.isInfinite(fv))
-                        constString = ((fv < 0) ? "-" : "") + "Inff";
-                    else
-                        constString = value.toString() + "f";
-                } else if (value instanceof Double) {
-                    /* bug for bug */
-                    double d = ((Double)value).doubleValue();
-                    if (Double.isInfinite(d))
-                        constString = ((d < 0) ? "-" : "") + "InfD";
-                    else
-                        constString = value.toString();
+    protected void writeMethods(PrintWriter out, ClassSymbol sym, String cname)
+            throws IOException, TypeSignature.SignatureException {
+        List<Symbol> classmethods = sym.getEnclosedElements();
+        for (Symbol md : classmethods) {
+            if (isNative(md)) {
+                TypeSignature newtypesig = new TypeSignature(types);
+                CharSequence methodName = md.getSimpleName();
+                boolean isOverloaded = false;
+                for (Symbol md2 : classmethods) {
+                    if ((md2 != md)
+                            && (methodName.equals(md2.getSimpleName()))
+                            && isNative(md2)) {
+                        isOverloaded = true;
+                    }
                 }
-
-                if (constString != null) {
-                    StringBuilder s = new StringBuilder("#undef ");
-                    s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
-                    s.append("#define "); s.append(cname); s.append("_");
-                    s.append(fname); s.append(" "); s.append(constString);
-                    return s.toString();
+                out.println("/*");
+                out.println(" * Class:     " + cname);
+                out.println(" * Method:    " + encode(methodName, EncoderType.FIELDSTUB));
+                out.println(" * Signature: " + newtypesig.getSignature(md.type));
+                out.println(" */");
+                out.println("JNIEXPORT " + jniType(types.erasure(md.type.getReturnType()))
+                        + " JNICALL " + encodeMethod(md, sym, isOverloaded));
+                out.print("  (JNIEnv *, ");
+                out.print((md.isStatic())
+                        ? "jclass"
+                        : "jobject");
+                for (Type arg : types.erasure(md.type.getParameterTypes())) {
+                    out.print(", ");
+                    out.print(jniType(arg));
                 }
-
-            }
-        }
-
-        return null;
-    }
-
-
-    protected void writeMethods(Writer out, ClassSymbol sym, String cname)
-            throws IOException, TypeSignature.SignatureException {
-        List<ExecutableElement> classmethods = ElementFilter.methodsIn(sym.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(elements);
-                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;
-
-                }
-                println(out, "/*");
-                println(out, " * Class:     " + cname);
-                println(out, " * Method:    " +
-                           mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
-                println(out, " * Signature: " + newtypesig.getTypeSignature(sig, mtr));
-                println(out, " */");
-                println(out, "JNIEXPORT " + jniType(mtr) +
-                           " JNICALL " +
-                           mangler.mangleMethod(md, sym,
-                                               (longName) ?
-                                               Mangle.Type.METHOD_JNI_LONG :
-                                               Mangle.Type.METHOD_JNI_SHORT));
-                print(out, "  (JNIEnv *, ");
-                List<? extends VariableElement> paramargs = md.getParameters();
-                List<TypeMirror> args = new ArrayList<>();
-                for (VariableElement p: paramargs) {
-                    args.add(types.erasure(p.asType()));
-                }
-                if (md.getModifiers().contains(Modifier.STATIC))
-                    print(out, "jclass");
-                else
-                    print(out, "jobject");
-
-                for (TypeMirror arg: args) {
-                    print(out, ", ");
-                    print(out, jniType(arg));
-                }
-                println(out, ");"
-                        + lineSep);
+                out.println(");");
+                out.println();
             }
         }
     }
-
-    // c.f. MethodDoc.signature
-    String signature(ExecutableElement e) {
-        StringBuilder sb = new StringBuilder("(");
-        String sep = "";
-        for (VariableElement p: e.getParameters()) {
-            sb.append(sep);
-            sb.append(types.erasure(p.asType()).toString());
-            sep = ",";
-        }
-        sb.append(")");
-        return sb.toString();
-    }
-
-    protected final String jniType(TypeMirror t) {
-        TypeElement throwable = elements.getTypeElement("java.lang.Throwable");
-        TypeElement jClass = elements.getTypeElement("java.lang.Class");
-        TypeElement jString = elements.getTypeElement("java.lang.String");
-        Element tclassDoc = types.asElement(t);
-
-
+    @SuppressWarnings("fallthrough")
+    protected final String jniType(Type t) {
         switch (t.getKind()) {
             case ARRAY: {
-                TypeMirror ct = ((ArrayType) t).getComponentType();
+                Type ct = ((Type.ArrayType)t).getComponentType();
                 switch (ct.getKind()) {
                     case BOOLEAN:  return "jbooleanArray";
                     case BYTE:     return "jbyteArray";
@@ -420,16 +343,16 @@
             case LONG:     return "jlong";
             case FLOAT:    return "jfloat";
             case DOUBLE:   return "jdouble";
-
             case DECLARED: {
-                if (tclassDoc.equals(jString))
+                if (t.tsym.type == syms.stringType) {
                     return "jstring";
-                else if (types.isAssignable(t, throwable.asType()))
+                } else if (types.isAssignable(t, syms.throwableType)) {
                     return "jthrowable";
-                else if (types.isAssignable(t, jClass.asType()))
+                } else if (types.isAssignable(t, syms.classType)) {
                     return "jclass";
-                else
+                } else {
                     return "jobject";
+                }
             }
         }
 
@@ -437,193 +360,145 @@
         return null; /* dead code. */
     }
 
-    protected String fileTop() {
-        return "/* DO NOT EDIT THIS FILE - it is machine generated */";
+    protected void  fileTop(PrintWriter out) {
+        out.println("/* DO NOT EDIT THIS FILE - it is machine generated */");
     }
 
-    protected String includes() {
-        return "#include <jni.h>";
+    protected void includes(PrintWriter out) {
+        out.println("#include <jni.h>");
     }
 
     /*
      * Deal with the C pre-processor.
      */
-    protected String cppGuardBegin() {
-        return "#ifdef __cplusplus" + lineSep
-                + "extern \"C\" {" + lineSep
-                + "#endif";
+    protected void cppGuardBegin(PrintWriter out) {
+        out.println("#ifdef __cplusplus");
+        out.println("extern \"C\" {");
+        out.println("#endif");
     }
 
-    protected String cppGuardEnd() {
-        return "#ifdef __cplusplus" + lineSep
-                + "}" + lineSep
-                + "#endif";
+    protected void cppGuardEnd(PrintWriter out) {
+        out.println("#ifdef __cplusplus");
+        out.println("}");
+        out.println("#endif");
     }
 
-    protected String guardBegin(String cname) {
-        return "/* Header for class " + cname + " */" + lineSep
-                + lineSep
-                + "#ifndef _Included_" + cname + lineSep
-                + "#define _Included_" + cname;
+    protected void guardBegin(PrintWriter out, String cname) {
+        out.println("/* Header for class " + cname + " */");
+        out.println();
+        out.println("#ifndef _Included_" + cname);
+        out.println("#define _Included_" + cname);
     }
 
-    protected String guardEnd(String cname) {
-        return "#endif";
+    protected void guardEnd(PrintWriter out) {
+        out.println("#endif");
     }
 
-    protected void print(Writer out, String text) throws IOException {
-        out.write(text);
+    String encodeMethod(Symbol msym, ClassSymbol clazz,
+            boolean isOverloaded) throws TypeSignature.SignatureException {
+        StringBuilder result = new StringBuilder(100);
+        result.append("Java_");
+        /* JNI */
+        result.append(encode(clazz.flatname.toString(), EncoderType.JNI));
+        result.append('_');
+        result.append(encode(msym.getSimpleName(), EncoderType.JNI));
+        if (isOverloaded) {
+            TypeSignature typeSig = new TypeSignature(types);
+            StringBuilder sig = typeSig.getParameterSignature(msym.type);
+            result.append("__").append(encode(sig, EncoderType.JNI));
+        }
+        return result.toString();
     }
 
-    protected void println(Writer out, String text) throws IOException {
-        out.write(text);
-        out.write(lineSep);
+    static enum EncoderType {
+        CLASS,
+        FIELDSTUB,
+        FIELD,
+        JNI,
+        SIGNATURE
+    }
+    @SuppressWarnings("fallthrough")
+    static String encode(CharSequence name, EncoderType mtype) {
+        StringBuilder result = new StringBuilder(100);
+        int length = name.length();
+
+        for (int i = 0; i < length; i++) {
+            char ch = name.charAt(i);
+            if (isalnum(ch)) {
+                result.append(ch);
+                continue;
+            }
+            switch (mtype) {
+                case CLASS:
+                    switch (ch) {
+                        case '.':
+                        case '_':
+                            result.append("_");
+                            break;
+                        case '$':
+                            result.append("__");
+                            break;
+                        default:
+                            result.append(encodeChar(ch));
+                    }
+                    break;
+                case JNI:
+                    switch (ch) {
+                        case '/':
+                        case '.':
+                            result.append("_");
+                            break;
+                        case '_':
+                            result.append("_1");
+                            break;
+                        case ';':
+                            result.append("_2");
+                            break;
+                        case '[':
+                            result.append("_3");
+                            break;
+                        default:
+                            result.append(encodeChar(ch));
+                    }
+                    break;
+                case SIGNATURE:
+                    result.append(isprint(ch) ? ch : encodeChar(ch));
+                    break;
+                case FIELDSTUB:
+                    result.append(ch == '_' ? ch : encodeChar(ch));
+                    break;
+                default:
+                    result.append(encodeChar(ch));
+            }
+        }
+        return result.toString();
     }
 
+    static String encodeChar(char ch) {
+        String s = Integer.toHexString(ch);
+        int nzeros = 5 - s.length();
+        char[] result = new char[6];
+        result[0] = '_';
+        for (int i = 1; i <= nzeros; i++) {
+            result[i] = '0';
+        }
+        for (int i = nzeros + 1, j = 0; i < 6; i++, j++) {
+            result[i] = s.charAt(j);
+        }
+        return new String(result);
+    }
 
-    private static class Mangle {
+    /* Warning: Intentional ASCII operation. */
+    private static boolean isalnum(char ch) {
+        return ch <= 0x7f && /* quick test */
+                ((ch >= 'A' && ch <= 'Z')  ||
+                 (ch >= 'a' && ch <= 'z')  ||
+                 (ch >= '0' && ch <= '9'));
+    }
 
-        public static class Type {
-            public static final int CLASS            = 1;
-            public static final int FIELDSTUB        = 2;
-            public static final int FIELD            = 3;
-            public static final int JNI              = 4;
-            public static final int SIGNATURE        = 5;
-            public static final int METHOD_JDK_1     = 6;
-            public static final int METHOD_JNI_SHORT = 7;
-            public static final int METHOD_JNI_LONG  = 8;
-        }
-
-        private Elements elems;
-        private Types types;
-
-        Mangle(Elements elems, Types types) {
-            this.elems = elems;
-            this.types = types;
-        }
-
-        public final String mangle(CharSequence name, int mtype) {
-            StringBuilder result = new StringBuilder(100);
-            int length = name.length();
-
-            for (int i = 0; i < length; i++) {
-                char ch = name.charAt(i);
-                if (isalnum(ch)) {
-                    result.append(ch);
-                } else if ((ch == '.') &&
-                           mtype == Mangle.Type.CLASS) {
-                    result.append('_');
-                } else if (( ch == '$') &&
-                           mtype == Mangle.Type.CLASS) {
-                    result.append('_');
-                    result.append('_');
-                } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) {
-                    result.append('_');
-                } else if (ch == '_' && mtype == Mangle.Type.CLASS) {
-                    result.append('_');
-                } else if (mtype == Mangle.Type.JNI) {
-                    String esc = null;
-                    if (ch == '_')
-                        esc = "_1";
-                    else if (ch == '.')
-                        esc = "_";
-                    else if (ch == ';')
-                        esc = "_2";
-                    else if (ch == '[')
-                        esc = "_3";
-                    if (esc != null) {
-                        result.append(esc);
-                    } else {
-                        result.append(mangleChar(ch));
-                    }
-                } else if (mtype == Mangle.Type.SIGNATURE) {
-                    if (isprint(ch)) {
-                        result.append(ch);
-                    } else {
-                        result.append(mangleChar(ch));
-                    }
-                } else {
-                    result.append(mangleChar(ch));
-                }
-            }
-
-            return result.toString();
-        }
-
-        public String mangleMethod(ExecutableElement method, TypeElement clazz,
-                                          int mtype) throws TypeSignature.SignatureException {
-            StringBuilder result = new StringBuilder(100);
-            result.append("Java_");
-
-            if (mtype == Mangle.Type.METHOD_JDK_1) {
-                result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS));
-                result.append('_');
-                result.append(mangle(method.getSimpleName(),
-                                     Mangle.Type.FIELD));
-                result.append("_stub");
-                return result.toString();
-            }
-
-            /* JNI */
-            result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
-            result.append('_');
-            result.append(mangle(method.getSimpleName(),
-                                 Mangle.Type.JNI));
-            if (mtype == Mangle.Type.METHOD_JNI_LONG) {
-                result.append("__");
-                String typesig = signature(method);
-                TypeSignature newTypeSig = new TypeSignature(elems);
-                String sig = newTypeSig.getTypeSignature(typesig,  method.getReturnType());
-                sig = sig.substring(1);
-                sig = sig.substring(0, sig.lastIndexOf(')'));
-                sig = sig.replace('/', '.');
-                result.append(mangle(sig, Mangle.Type.JNI));
-            }
-
-            return result.toString();
-        }
-        //where
-            private String getInnerQualifiedName(TypeElement clazz) {
-                return elems.getBinaryName(clazz).toString();
-            }
-
-        public final String mangleChar(char ch) {
-            String s = Integer.toHexString(ch);
-            int nzeros = 5 - s.length();
-            char[] result = new char[6];
-            result[0] = '_';
-            for (int i = 1; i <= nzeros; i++)
-                result[i] = '0';
-            for (int i = nzeros+1, j = 0; i < 6; i++, j++)
-                result[i] = s.charAt(j);
-            return new String(result);
-        }
-
-        // Warning: duplicated in Gen
-        private String signature(ExecutableElement e) {
-            StringBuilder sb = new StringBuilder();
-            String sep = "(";
-            for (VariableElement p: e.getParameters()) {
-                sb.append(sep);
-                sb.append(types.erasure(p.asType()).toString());
-                sep = ",";
-            }
-            sb.append(")");
-            return sb.toString();
-        }
-
-        /* Warning: Intentional ASCII operation. */
-        private static boolean isalnum(char ch) {
-            return ch <= 0x7f && /* quick test */
-                ((ch >= 'A' && ch <= 'Z') ||
-                 (ch >= 'a' && ch <= 'z') ||
-                 (ch >= '0' && ch <= '9'));
-        }
-
-        /* Warning: Intentional ASCII operation. */
-        private static boolean isprint(char ch) {
-            return ch >= 32 && ch <= 126;
-        }
+    /* Warning: Intentional ASCII operation. */
+    private static boolean isprint(char ch) {
+        return ch >= 32 && ch <= 126;
     }
 
     private static class TypeSignature {
@@ -634,10 +509,10 @@
             }
         }
 
-        Elements elems;
+        JavacElements elems;
+        Types    types;
 
         /* Signature Characters */
-
         private static final String SIG_VOID                   = "V";
         private static final String SIG_BOOLEAN                = "Z";
         private static final String SIG_BYTE                   = "B";
@@ -650,209 +525,162 @@
         private static final String SIG_ARRAY                  = "[";
         private static final String SIG_CLASS                  = "L";
 
+        public TypeSignature(Types types) {
+            this.types = types;
+        }
 
+        StringBuilder getParameterSignature(Type mType)
+                throws SignatureException {
+            StringBuilder result = new StringBuilder();
+            for (Type pType : mType.getParameterTypes()) {
+                result.append(getJvmSignature(pType));
+            }
+            return result;
+        }
 
-        public TypeSignature(Elements elems){
-            this.elems = elems;
+        StringBuilder getReturnSignature(Type mType)
+                throws SignatureException {
+            return getJvmSignature(mType.getReturnType());
+        }
+
+        StringBuilder getSignature(Type mType) throws SignatureException {
+            StringBuilder sb = new StringBuilder();
+            sb.append("(").append(getParameterSignature(mType)).append(")");
+            sb.append(getReturnSignature(mType));
+            return sb;
         }
 
         /*
-         * Returns the type signature of a field according to JVM specs
+         * Returns jvm internal signature.
          */
-        public String getTypeSignature(String javasignature) throws SignatureException {
-            return getParamJVMSignature(javasignature);
+        static class JvmTypeVisitor extends JNIWriter.SimpleTypeVisitor<Type, StringBuilder> {
+
+            @Override
+            public Type visitClassType(Type.ClassType t, StringBuilder s) {
+                setDeclaredType(t, s);
+                return null;
+            }
+
+            @Override
+            public Type visitArrayType(Type.ArrayType t, StringBuilder s) {
+                s.append("[");
+                return t.getComponentType().accept(this, s);
+            }
+
+            @Override
+            public Type visitType(Type t, StringBuilder s) {
+                if (t.isPrimitiveOrVoid()) {
+                    s.append(getJvmPrimitiveSignature(t));
+                    return null;
+                }
+                return t.accept(this, s);
+            }
+            private void setDeclaredType(Type t, StringBuilder s) {
+                    String classname = t.tsym.getQualifiedName().toString();
+                    classname = classname.replace('.', '/');
+                    s.append("L").append(classname).append(";");
+            }
+            private String getJvmPrimitiveSignature(Type t) {
+                switch (t.getKind()) {
+                    case VOID:      return SIG_VOID;
+                    case BOOLEAN:   return SIG_BOOLEAN;
+                    case BYTE:      return SIG_BYTE;
+                    case CHAR:      return SIG_CHAR;
+                    case SHORT:     return SIG_SHORT;
+                    case INT:       return SIG_INT;
+                    case LONG:      return SIG_LONG;
+                    case FLOAT:     return SIG_FLOAT;
+                    case DOUBLE:    return SIG_DOUBLE;
+                    default:
+                        Assert.error("unknown type: should not happen");
+                }
+                return null;
+            }
         }
 
-        /*
-         * Returns the type signature of a method according to JVM specs
-         */
-        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<>(); //List of parameters.
-            String paramsig = null; //Java parameter signature.
-            String paramJVMSig = null; //Internal parameter signature.
-            String returnSig = null; //Java return type signature.
-            String returnJVMType = null; //Internal return type signature.
-            int dimensions = 0; //Array dimension.
-
-            int startIndex = -1;
-            int endIndex = -1;
-            StringTokenizer st = null;
-            int i = 0;
-
-            // Gets the actual java signature without parentheses.
-            if (javasignature != null) {
-                startIndex = javasignature.indexOf("(");
-                endIndex = javasignature.indexOf(")");
-            }
-
-            if (((startIndex != -1) && (endIndex != -1))
-                &&(startIndex+1 < javasignature.length())
-                &&(endIndex < javasignature.length())) {
-                signature = javasignature.substring(startIndex+1, endIndex);
-            }
-
-            // Separates parameters.
-            if (signature != null) {
-                if (signature.contains(",")) {
-                    st = new StringTokenizer(signature, ",");
-                    if (st != null) {
-                        while (st.hasMoreTokens()) {
-                            params.add(st.nextToken());
-                        }
-                    }
-                } else {
-                    params.add(signature);
-                }
-            }
-
-            /* JVM type signature. */
-            typeSignature = "(";
-
-            // Gets indivisual internal parameter signature.
-            while (params.isEmpty() != true) {
-                paramsig = params.remove(i).trim();
-                paramJVMSig  = getParamJVMSignature(paramsig);
-                if (paramJVMSig != null) {
-                    typeSignature += paramJVMSig;
-                }
-            }
-
-            typeSignature += ")";
-
-            // Get internal return type signature.
-
-            returnJVMType = "";
-            if (returnType != null) {
-                dimensions = dimensions(returnType);
-            }
-
-            //Gets array dimension of return type.
-            while (dimensions-- > 0) {
-                returnJVMType += "[";
-            }
-            if (returnType != null) {
-                returnSig = qualifiedTypeName(returnType);
-                returnJVMType += getComponentType(returnSig);
-            } else {
-                System.out.println("Invalid return type.");
-            }
-
-            typeSignature += returnJVMType;
-
-            return typeSignature;
-        }
-
-        /*
-         * Returns internal signature of a parameter.
-         */
-        private String getParamJVMSignature(String paramsig) throws SignatureException {
-            String paramJVMSig = "";
-            String componentType ="";
-
-            if(paramsig != null){
-
-                if(paramsig.contains("[]")) {
-                    // Gets array dimension.
-                    int endindex = paramsig.indexOf("[]");
-                    componentType = paramsig.substring(0, endindex);
-                    String dimensionString =  paramsig.substring(endindex);
-                    if(dimensionString != null){
-                        while(dimensionString.contains("[]")){
-                            paramJVMSig += "[";
-                            int beginindex = dimensionString.indexOf("]") + 1;
-                            if(beginindex < dimensionString.length()){
-                                dimensionString = dimensionString.substring(beginindex);
-                            }else
-                                dimensionString = "";
-                        }
-                    }
-                } else componentType = paramsig;
-
-                paramJVMSig += getComponentType(componentType);
-            }
-            return paramJVMSig;
-        }
-
-        /*
-         * Returns internal signature of a component.
-         */
-        private String getComponentType(String componentType) throws SignatureException {
-
-            String JVMSig = "";
-
-            if(componentType != null){
-                switch (componentType) {
-                    case "void":    JVMSig += SIG_VOID;    break;
-                    case "boolean": JVMSig += SIG_BOOLEAN; break;
-                    case "byte":    JVMSig += SIG_BYTE;    break;
-                    case "char":    JVMSig += SIG_CHAR;    break;
-                    case "short":   JVMSig += SIG_SHORT;   break;
-                    case "int":     JVMSig += SIG_INT;     break;
-                    case "long":    JVMSig += SIG_LONG;    break;
-                    case "float":   JVMSig += SIG_FLOAT;   break;
-                    case "double":  JVMSig += SIG_DOUBLE;  break;
-                    default:
-                        if (!componentType.equals("")) {
-                            TypeElement classNameDoc = elems.getTypeElement(componentType);
-
-                            if (classNameDoc == null) {
-                                throw new SignatureException(componentType);
-                            }
-                            else {
-                                String classname = classNameDoc.getQualifiedName().toString();
-                                String newclassname = classname.replace('.', '/');
-                                JVMSig += "L";
-                                JVMSig += newclassname;
-                                JVMSig += ";";
-                            }
-                        }
-                        break;
-                }
-            }
-            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 SimpleTypeVisitor8<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();
+        StringBuilder getJvmSignature(Type type) {
+            Type t = types.erasure(type);
+            StringBuilder sig = new StringBuilder();
+            JvmTypeVisitor jv = new JvmTypeVisitor();
+            jv.visitType(t, sig);
+            return sig;
         }
     }
 
+    static class SimpleTypeVisitor<R, P> implements Type.Visitor<R, P> {
+
+        protected final R DEFAULT_VALUE;
+
+        protected SimpleTypeVisitor() {
+            DEFAULT_VALUE = null;
+        }
+
+        protected SimpleTypeVisitor(R defaultValue) {
+            DEFAULT_VALUE = defaultValue;
+        }
+
+        protected R defaultAction(Type t, P p) {
+            return DEFAULT_VALUE;
+        }
+
+        @Override
+        public R visitClassType(Type.ClassType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitWildcardType(Type.WildcardType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitArrayType(Type.ArrayType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitMethodType(Type.MethodType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitPackageType(Type.PackageType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitTypeVar(Type.TypeVar t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitCapturedType(Type.CapturedType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitForAll(Type.ForAll t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitUndetVar(Type.UndetVar t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitErrorType(Type.ErrorType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitAnnotatedType(Type.AnnotatedType t, P p) {
+            return defaultAction(t, p);
+        }
+
+        @Override
+        public R visitType(Type t, P p) {
+            return defaultAction(t, p);
+        }
+    }
 }
--- a/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java	Fri Feb 14 17:28:07 2014 -0800
+++ b/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java	Sat Feb 15 16:37:19 2014 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 7150368 8003412 8000407
+ * @bug 7150368 8003412 8000407 8031545
  * @summary javac should include basic ability to generate native headers
  */
 
--- a/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java	Fri Feb 14 17:28:07 2014 -0800
+++ b/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java	Sat Feb 15 16:37:19 2014 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2014, 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
@@ -129,50 +129,52 @@
     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 bmo() { return 0; }
+    short smo() { return 0; }
+    int imo() { return 0; }
+    long lmo() { return 0; }
+    float fmo() { return 0; }
+    double dmo() { return 0; }
+    Object omo() { return null; }
+    String tmo() { return ""; }
+    List<String> gmo() { return null; }
+    void vmo() { }
 
-    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) { }
+    byte bmo(int i) { return 0; }
+    short smo(int i) { return 0; }
+    int imo(int i) { return 0; }
+    long lmo(int i) { return 0; }
+    float fmo(int i) { return 0; }
+    double dmo(int i) { return 0; }
+    Object omo(int i) { return null; }
+    String tmo(int i) { return ""; }
+    List<String> gmo(int i) { return null; }
+    void vmo(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 bmno();
+    native short smno();
+    native int imno();
+    native long lmno();
+    native float fmno();
+    native double dmno();
+    native Object omno();
+    native String tmno();
+    native List<String> gmno();
+    native void vmno();
+    native Inner1 icmno();
 
-    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);
+    native byte bmno(int i);
+    native short smno(int i);
+    native int imno(int i);
+    native long lmno(int i);
+    native float fmno(int i);
+    native double dmno(int i);
+    native Object omno(int i);
+    native String tmno(int i);
+    native List<String> gmno(int i);
+    native void vmno(int i);
+    native Inner1 icmno(Inner1 in1);
 
     // arg types for Java methods
     void mb(byte b) { }
@@ -266,50 +268,50 @@
         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 bmo() { return 0; }
+        short smo() { return 0; }
+        int imo() { return 0; }
+        long lmo() { return 0; }
+        float fmo() { return 0; }
+        double dmo() { return 0; }
+        Object omo() { return null; }
+        String tmo() { return ""; }
+        List<String> gmo() { return null; }
+        void vmo() { }
 
-        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) { }
+        byte bmo(int i) { return 0; }
+        short smo(int i) { return 0; }
+        int imo(int i) { return 0; }
+        long lmo(int i) { return 0; }
+        float fmo(int i) { return 0; }
+        double dmo(int i) { return 0; }
+        Object omo(int i) { return null; }
+        String tmo(int i) { return ""; }
+        List<String> gmo(int i) { return null; }
+        void vmo(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 bmno();
+        native short smno();
+        native int imno();
+        native long lmno();
+        native float fmno();
+        native double dmno();
+        native Object omno();
+        native String tmno();
+        native List<String> gmno();
+        native void vmno();
 
-        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);
+        native byte bmno(int i);
+        native short smno(int i);
+        native int imno(int i);
+        native long lmno(int i);
+        native float fmno(int i);
+        native double dmno(int i);
+        native Object omno(int i);
+        native String tmno(int i);
+        native List<String> gmno(int i);
+        native void vmno(int i);
 
         // arg types for Java methods
         void mb(byte b) { }