你正在使用的Go版本是什么(go version
)?
$ go version
go version go1.20 windows/amd64
这个问题在最新版本的发布中是否会重现?
是的
你正在使用什么操作系统和处理器架构(go env
)?go env
输出
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\green\AppData\Local\go-build
set GOENV=C:\Users\green\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\green\go\pkg\mod
set GONOPROXY=github.com/MetaFFI/*,github.com/GreenFuze/*
set GONOSUMDB=github.com/MetaFFI/*,github.com/GreenFuze/*
set GOOS=windows
set GOPATH=C:\Users\green\go
set GOPRIVATE=github.com/MetaFFI/*,github.com/GreenFuze/*
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.20
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=NUL
set GOWORK=
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=c:\temp\go-build2999029303=/tmp/go-build -gno-record-gcc-switches
你做了什么?
当"runtime/signal_windows.go:168"中的"var testingWER bool"为false时,以下代码会在运行时崩溃。
package main
/*
#include <Windows.h>
#include <stdio.h>
typedef struct JavaVMInitArgs {
int version;
int nOptions;
void *options;
unsigned char ignoreUnrecognized;
} JavaVMInitArgs;
void create_jvm()
{
HMODULE h = LoadLibrary("C:\\Program Files\\Microsoft\\jdk-11.0.18.10-hotspot\\bin\\server\\jvm.dll");
void* create = GetProcAddress(h, "JNI_CreateJavaVM");
JavaVMInitArgs vm_args;
vm_args.version = 0x000a0000; //JNI_VERSION_10
vm_args.nOptions = 0;
vm_args.options = 0;
vm_args.ignoreUnrecognized = 0;
void* pjvm = 0;
void* penv = 0;
printf("Before calling JNI_CreateJavaVM\r\n");
((void(*)(void**, void**, JavaVMInitArgs*))create)(&pjvm, &penv, &vm_args);
printf("After calling JNI_CreateJavaVM\r\n");
}
*/
import "C"
func main(){
C.create_jvm();
}
将"var testingWER bool"更改为true,使应用程序正常工作。
你期望看到什么?
它不会崩溃
你看到了什么?
JNI_CreateJavaVM因ACCESS_VIOLATION而崩溃。
解决方案建议
问题在于由JNI(并被其捕获)生成的ACCESS_VIOLATION没有被捕获,原因是Go没有继续异常搜索(即_EXCEPTION_CONTINUE_SEARCH)。
将Go修补为"testingWER=true"强制Go继续搜索,允许JNI处理错误。
作为短期解决方案,我建议将"testingWER"设置为公共变量,这样开发人员可以在不修补Go的情况下解决意外问题。
作为长期解决方案,如果Go模块是库或存档,则signal_windows.go应返回_EXCEPTION_CONTINUE_SEARCH。我建议执行以下操作之一:
- 如果正在使用CGo,则返回_EXCEPTION_CONTINUE_SEARCH,因为走出"Go运行时"可能需要自定义异常处理。
- 为用户提供一个函数来替换signal_windows.go中的"lastcontinuehandler",用他们自己的。我认为这是最佳选项,因为我们在Go意识到无法处理异常之后才达到这一点,所以让用户采取一些行动。您还可以将引发异常的代码(winthrow()函数)作为参数传递给用户的自定义"lastcontinuehandler"。
8条答案
按热度按时间csbfibhn1#
(CC @golang/windows)
kpbpu0082#
比较 #57441 , #52763 , #19465 。
xjreopfe3#
与 #56082、#47576 和 #12516 相关。
huwehgph4#
在版本go1.21.1中,测试WER已被移除,但JVM仍然崩溃。目前我无法找到使用JNI_CreateJavaVM在Windows上加载JVM的解决方法。有人能提供一个解决方案吗?
66bbxpm55#
我有一些CL(CL 525475和CL 457875)正在飞行,它们将教导Go运行时在异常被捕获并由SEH异常处理程序处理时不崩溃。这应该解决了你的问题。
有人能提供一个解决方法吗?
如果你之前修补过Go,我建议你继续这样做,即重新添加
testingWER
。oiopk7p56#
你好,
我想问一下,在不久的将来的GO版本中是否会修复上述提到的问题?
感谢更新。
f3temu5u7#
尚未,我无法及时降落CL 457875,因为我被SEH机器中的一个重要缺失部分所分心(参见CL 534555)。我的计划是在go 1.23中解决这个问题。
bjp0bcyl8#
https://go.dev/cl/457875提到了这个问题:
runtime,cmd/link: use SEH instead of vectored exception handlers