13

我尝试从如下所示的 Google Go 程序启动 JVM:

package main
import "fmt"
import "os"
import "log"
func main() {

var name string
name="\\jrex64\\bin\\java.exe"

var path="-Xbootclasspath:jrex64\\lib\\rt.jar;"+
"jrex64\\lib\\jfxrt.jar;"+
"jrex64\\lib\\resources.jar;"+
"jrex64\\lib\\ext\\sunjce_provider.jar;"+
"jrex64\\lib\\ext\\zipfs.jar;"+
"jrex64\\lib\\ext\\sunmscapi.jar;"+
"jrex64\\lib\\ext\\sunec.jar;"+
"jrex64\\lib\\ext\\dnsns.jar;"+
"jrex64\\lib\\ext\\access-bridge-64.jar;"+
"jrex64\\lib\\security\\local_policy.jar;"+
"jrex64\\lib\\jce.jar;"+
"jrex64\\lib\\jfr.jar;"+
"jrex64\\lib\\jsse.jar;"+
"jrex64\\lib\\charsets.jar;"+
"jrex64\\lib\\";



var args[] string=make([]string,4)
args[0]="-verbose"
args[1]=path;
args[2]="-cp Ganesha_lib\\*"
args[3]="-jar Ganesha.jar"

var attr* os.ProcAttr

proc,err:=os.StartProcess(name,args,attr)
proc.Wait();


if err!=nil {
    fmt.Println("an error occurred.\n")
    log.Fatal(err)
}

}

这是我的第一个围棋程序。而且我完全被以下错误所淹没:

恐慌:运行时错误:无效的内存地址或 nil 指针取消引用 [信号 0xc0000005 代码=0x0 地址=0x0 pc=0x4278b5] goroutine 1 [运行]:os.startProcess(0x4aacb4, 0x14, 0xf840001eb0, 0x500000005, 0x0, ...) C :/Users/ADMINI~1/AppData/Local/Temp/2/bindist767862039/go/src/pkg/os/exec_posix.go:28 +0x152 os.StartProcess(0x4aacb4, 0x14, 0xf840001eb0, 0x500000005, 0x0, ... ) C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist767862039/go/src/pkg/os/doc.go:24 +0x5c main.main() D:/MyGoProject/src/main.go :60 +0x23c goroutine 2 [syscall]: 由 runtime.main 创建 C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist767862039/go/src/pkg/runtime/proc.c:221 进程完成退出代码 2

我该如何解释这个错误代码?什么地方出了错?以及如何获得 JVM startet - 它位于 Go 可执行文件的子目录中。

4

4 回答 4

18

通常建议您不要直接使用 os.StartProcess。相反,使用 os/exec 具有更简单的界面。这是我将如何启动一个 java 子进程并等待它完成的方法。

http://play.golang.org/p/APlp9KK9wx

package main

import (
    "fmt"
    "log"
    "os/exec"
    "strings"
)

func main() {
    var java = "\\jrex64\\bin\\java.exe"

    var path = []string{
        "jrex64\\lib\\rt.jar",
        "jrex64\\lib\\jfxrt.jar",
        "jrex64\\lib\\resources.jar",
        "jrex64\\lib\\ext\\sunjce_provider.jar",
        "jrex64\\lib\\ext\\zipfs.jar",
        "jrex64\\lib\\ext\\sunmscapi.jar",
        "jrex64\\lib\\ext\\sunec.jar",
        "jrex64\\lib\\ext\\dnsns.jar",
        "jrex64\\lib\\ext\\access-bridge-64.jar",
        "jrex64\\lib\\security\\local_policy.jar",
        "jrex64\\lib\\jce.jar",
        "jrex64\\lib\\jfr.jar",
        "jrex64\\lib\\jsse.jar",
        "jrex64\\lib\\charsets.jar",
        "jrex64\\lib\\",
    }

    pathflag := "-Xbootclasspath:" + strings.Join(path, ";")
    cmd := exec.Command(java, "-verbose", pathflag, "-cp Ganesha_lib\\*", "-jar Ganesha.jar")
    err := cmd.Run()

    if err != nil {
        fmt.Println("an error occurred.\n")
        log.Fatal(err)
    }

}

如果你很好奇,你会感到恐慌的原因是 attr 是一个 nil 指针。相反,您本可以完成attr := new(os.ProcAttr).

于 2012-12-17T16:42:37.863 回答
10

前面的答案实际上并没有描述如何使用 os.StartProcess()。这是一个例子:

cmdToRun := "/path/to/someCommand"
args := []string{"someCommand", "arg1"}
procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
if process, err := os.StartProcess(cmdToRun, args, procAttr); err != nil {
    fmt.Printf("ERROR Unable to run %s: %s\n", cmdToRun, err.Error())
} else {
    fmt.Printf("%s running as pid %d\n", cmdToRun, process.Pid)
}

请注意,有必要初始化 ProcAttr.Files 字段 - 如果不这样做,您可能会在 os 包的深处得到索引越界错误。如果您想在自己的代码中提供来自新进程的输入或进程输出,则可以对文件使用管道。您可能还想指定 Dir(起始目录)和 Env(环境变量)字段。

于 2015-07-03T00:34:40.863 回答
2

这里:

var attr* os.ProcAttr

proc, err := os.StartProcess(name, args, attr)

attr变量为 nil,当在其中取消引用时os.StartProcess会导致您看到的错误。

于 2012-12-17T11:53:59.450 回答
0

在 Windows 上,os.ProcAttr 不能留空。At Dir 必须设置为空字符串,Sys 必须设置为 &syscall.SysProcAttr{}。以下应该有效:

name := "\\jrex64\\bin\\java.exe"
libs := "-Xbootclasspath:jrex64\\lib\\rt.jar;" +
    // add all libs
    "jrex64\\lib\\";
args := []string{"-verbose", libs, "-cp Ganesha_lib\\*", "-jar Ganesha.jar"}
attr := &os.ProcAttr{
    "",
    nil,
    []*os.File{os.Stdin, os.Stdout, os.Stderr},
    &syscall.SysProcAttr{}} //CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP, } 
}

proc, err := os.StartProcess(name,args,attr);
if err != nil {
    log.Fatalf("start process: %v", err)
}
_, err = proc.Wait();
if err != nil {
    log.Fatalf("wait: %v", err)
}
于 2021-11-21T15:40:55.817 回答