bind: preserve no-arg Java constructors

When the Java class parser began culling unused constructors, the
logic for determining whether a given Java class has a no-arg
constructor broke when the no-arg constructor is culled. Add
an explicit field for tracking the no-arg constructor property.

Change-Id: Ib68929ae1108bd6fa1fd23de1d134332eb0d97a2
Reviewed-on: https://go-review.googlesource.com/29875
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Elias Naur
2016-09-30 14:00:14 +00:00
parent 1663ffa95c
commit 2dcaa053a0
5 changed files with 37 additions and 15 deletions
+9 -13
View File
@@ -34,8 +34,8 @@ type javaClassInfo struct {
// All Java classes and interfaces this class extends and implements.
supers []*java.Class
methods map[string]*java.Func
// Does the extended class include a noarg constructor
hasNoargCon bool
// Does the class need a default no-arg constructor
genNoargCon bool
// Constructors for the type, on the form
// func New<Type>(...) *Type
cons []*types.Func
@@ -57,7 +57,7 @@ func (g *JavaGen) Init(classes []*java.Class) {
}
inf := &javaClassInfo{
methods: make(map[string]*java.Func),
hasNoargCon: true, // java.lang.Object has a noarg constructor
genNoargCon: true, // java.lang.Object has a no-arg constructor
}
for _, n := range classes {
cls := g.clsMap[n]
@@ -76,13 +76,7 @@ func (g *JavaGen) Init(classes []*java.Class) {
g.errorf("%s embeds final Java class %s", s.obj, cls.Name)
}
inf.extends = cls
inf.hasNoargCon = false
for _, f := range cls.Funcs {
if f.Constructor && len(f.Params) == 0 {
inf.hasNoargCon = true
break
}
}
inf.genNoargCon = cls.HasNoArgCon
}
}
g.jstructs[s.obj] = inf
@@ -91,6 +85,8 @@ func (g *JavaGen) Init(classes []*java.Class) {
if t := g.constructorType(f); t != nil {
jinf := g.jstructs[t]
if jinf != nil {
sig := f.Type().(*types.Signature)
jinf.genNoargCon = jinf.genNoargCon && sig.Params().Len() > 0
jinf.cons = append(jinf.cons, f)
}
}
@@ -181,7 +177,7 @@ func (g *JavaGen) genStruct(s structInfo) {
}
g.genConstructor(f, n)
}
if jinf.hasNoargCon {
if jinf.genNoargCon {
// Generate constructor for Go instantiated instances.
g.Printf("%s(Seq.Ref ref) { this.ref = ref; }\n\n", n)
// Generate default no-arg constructor
@@ -1279,7 +1275,7 @@ func (g *JavaGen) GenC() error {
if jinf, ok := g.jstructs[s.obj]; ok {
// Leave the class and constructor NULL for Java classes with no
// default constructor.
if !jinf.hasNoargCon {
if !jinf.genNoargCon {
continue
}
}
@@ -1328,7 +1324,7 @@ func (g *JavaGen) GenC() error {
for _, f := range jinf.cons {
g.genJNIConstructor(f, sName)
}
if jinf.hasNoargCon {
if jinf.genNoargCon {
g.Printf("JNIEXPORT jobject JNICALL\n")
g.Printf("Java_%s_%s_%s(JNIEnv *env, jclass clazz) {\n", g.jniPkgName(), sName, java.JNIMangle("__New"))
g.Indent()
+9
View File
@@ -125,6 +125,9 @@ Java_go_java_Java__1init(JNIEnv *env, jclass _unused) {
clazz = (*env)->FindClass(env, "go/java/Future");
proxy_class_java_Future = (*env)->NewGlobalRef(env, clazz);
proxy_class_java_Future_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
clazz = (*env)->FindClass(env, "go/java/Object");
proxy_class_java_Object = (*env)->NewGlobalRef(env, clazz);
proxy_class_java_Object_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
clazz = (*env)->FindClass(env, "go/java/Runnable");
proxy_class_java_Runnable = (*env)->NewGlobalRef(env, clazz);
proxy_class_java_Runnable_cons = (*env)->GetMethodID(env, clazz, "<init>", "(Lgo/Seq$Ref;)V");
@@ -207,6 +210,12 @@ Java_go_java_InputStream_getInputStream(JNIEnv *env, jobject this) {
return _r0;
}
JNIEXPORT jobject JNICALL
Java_go_java_Object__1_1New(JNIEnv *env, jclass clazz) {
int32_t refnum = new_java_Object();
return go_seq_from_refnum(env, refnum, NULL, NULL);
}
JNIEXPORT void JNICALL
Java_go_java_Object_setObject(JNIEnv *env, jobject this, jobject v) {
int32_t o = go_seq_to_refnum(env, this);
+6
View File
@@ -75,6 +75,12 @@ public final class Object extends java.lang.Object implements Seq.GoObject {
private final Seq.Ref ref;
Object(Seq.Ref ref) { this.ref = ref; }
public Object() { this.ref = __New(); }
private static native Seq.Ref __New();
@Override public final int incRefnum() {
int refnum = ref.refnum;
Seq.incGoRef(refnum);
+4
View File
@@ -145,3 +145,7 @@ func NewJavaObject() lang.Object {
func NewJavaInteger() lang.Integer {
return Integer.New_I(42)
}
type NoargConstructor struct {
util.BitSet // An otherwise unused class with a no-arg constructor
}
+9 -2
View File
@@ -46,6 +46,8 @@ type Class struct {
Abstract bool
Interface bool
Throwable bool
// Whether the class has a no-arg constructor
HasNoArgCon bool
}
// Func is a Java static function or method or constructor.
@@ -444,8 +446,12 @@ func (j *importer) scanClass(s *bufio.Scanner, name string) (*Class, error) {
if err != nil {
return nil, err
}
if len(cls.Supers) == 0 && name != "java.lang.Object" {
cls.Supers = append(cls.Supers, "java.lang.Object")
if len(cls.Supers) == 0 {
if name == "java.lang.Object" {
cls.HasNoArgCon = true
} else {
cls.Supers = append(cls.Supers, "java.lang.Object")
}
}
cls.JNIName = JNIMangle(cls.Name)
clsElems := strings.Split(cls.Name, ".")
@@ -503,6 +509,7 @@ func (j *importer) scanClass(s *bufio.Scanner, name string) (*Class, error) {
f.Final = final
f.Constructor = f.Name == cls.FindName
if f.Constructor {
cls.HasNoArgCon = cls.HasNoArgCon || len(f.Params) == 0
f.Public = f.Public && !cls.Abstract
f.Name = "new"
f.Ret = &Type{Class: name, Kind: Object}