go: cmd/cgo: jmethodID/jfieldID is not mapped to uintptr if building with the Android NDK

This is a variant of #26213

What version of Go are you using (go version)?

$ go version
go version go1.13.8 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/steeve/Library/Caches/go-build"
GOENV="/Users/steeve/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/steeve/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.14.5/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.14.5/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/steeve/code/github.com/znly/zenly-client-core/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/td/p8xt8d953g37w9f841byty940000gn/T/go-build199341614=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

package blah

/*
#include <jni.h>
*/
import "C"

var blah C.jmethodID = 0
var bleh C.jfieldID = 0

with the Android NDK:

$ CC=/path/to/ndk-standalone-x86_64/bin/clang CGO_ENABLED=1 GOOS=android go build program.go

What did you expect to see?

No error.

What did you see instead?

# command-line-arguments
./program.go:8: cannot use 0 (type int) as type _Ctype_jmethodID in assignment

Notes

This issue is the same as #26213, only with jmethodID and jfieldID. It seems the bug was always there, but for some reason it now reliably crashes on Android 11 with the following:

08-21 16:33:21.842 15438     0 E Go      : runtime: bad pointer in frame github.com/mypkg.func1 at 0x40000bfc70: 0x71
08-21 16:33:21.842 15438     0 E Go      : fatal error: invalid pointer found on stack
08-21 16:33:21.898 15438     0 E Go      : 
08-21 16:33:21.898 15438     0 E Go      : runtime stack:
08-21 16:33:21.899 15438     0 E Go      : runtime.throw(0x7b60f3d00a, 0x1e)
08-21 16:33:21.899 15438     0 E Go      :  GOROOT/src/runtime/panic.go:847 +0x4c fp=0x7b4c4ab3e0 sp=0x7b4c4ab3b0 pc=0x7b612d594c
08-21 16:33:21.899 15438     0 E Go      : runtime.adjustpointers(0x40000bfc68, 0x7b4c4ab4c8, 0x7b4c4ab8b8, 0x7b62c0acd0, 0x7b630d0780)
08-21 16:33:21.899 15438     0 E Go      :  GOROOT/src/runtime/stack.go:591 +0x1dc fp=0x7b4c4ab430 sp=0x7b4c4ab3e0 pc=0x7b612ecc7c
08-21 16:33:21.899 15438     0 E Go      : runtime.adjustframe(0x7b4c4ab7c0, 0x7b4c4ab8b8, 0x7b630d0780)
08-21 16:33:21.899 15438     0 E Go      :  GOROOT/src/runtime/stack.go:633 +0x260 fp=0x7b4c4ab4f0 sp=0x7b4c4ab430 pc=0x7b612ecef0
08-21 16:33:21.899 15438     0 E Go      : runtime.gentraceback(0xffffffffffffffff, 0xffffffffffffffff, 0x0, 0x40000b3500, 0x0, 0x0, 0x7fffffff, 0x7b625ed288, 0x7b4c4ab8b8, 0x0, ...)
08-21 16:33:21.899 15438     0 E Go      :  GOROOT/src/runtime/traceback.go:334 +0xd4c fp=0x7b4c4ab820 sp=0x7b4c4ab4f0 pc=0x7b612f705c
08-21 16:33:21.899 15438     0 E Go      : runtime.copystack(0x40000b3500, 0x1000, 0x7ca8b3bc01)
08-21 16:33:21.899 15438     0 E Go      :  GOROOT/src/runtime/stack.go:886 +0x1b4 fp=0x7b4c4ab9e0 sp=0x7b4c4ab820 pc=0x7b612ed484
08-21 16:33:21.899 15438     0 E Go      : runtime.newstack()
08-21 16:33:21.899 15438     0 E Go      :  GOROOT/src/runtime/stack.go:1055 +0x24c fp=0x7b4c4abb80 sp=0x7b4c4ab9e0 pc=0x7b612ed7bc
08-21 16:33:21.899 15438     0 E Go      : runtime.morestack()
08-21 16:33:21.899 15438     0 E Go      :  src/runtime/asm_arm64.s:310 +0x70 fp=0x7b4c4abb80 sp=0x7b4c4abb80 pc=0x7b613003b0

We are running a modified 1.13.8 and adding jmethodID and jfieldID to the list of badJNI types fixes the issue.

They are defined like so in Android NDK:

struct _jfieldID;                       /* opaque structure */
typedef struct _jfieldID* jfieldID;     /* field IDs */

struct _jmethodID;                      /* opaque structure */
typedef struct _jmethodID* jmethodID;   /* method IDs */

I’ll open a PR with the patch.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 46 (32 by maintainers)

Commits related to this issue

Most upvoted comments

Gentle ping. What to do for Go 1.15, and can we get rid of the special cases in Go 1.16 with go:notinheap?

I think the suggested plan is:

  1. change cgo to treat jmethodID and jfieldID like jobject (https://golang.org/cl/249744)
  2. backport that change to the 1.15 release branch and possibly the 1.14 release branch
  3. change cgo (in 1.16 only) to mark empty structs as notinheap (https://golang.org/cl/250940)

Does that sound right to everyone?

@randall77 Any objections to this plan?

I think my series of CLs solves this issue, and maybe future such issues going forward as well. The only thing I worry about is that these CLs are a bit subtle, so backporting them is a nontrivial risk. Do we need to backport? Is there another possible workaround? Can Android 11 wait for 1.16 to come out?