Как начать процесс?

Я пытаюсь запустить JVM из программы Google Go, которая выглядит так:

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)
}

}

Это моя первая программа Go. И я полностью перегружен, получив следующую ошибку:

panic: ошибка времени выполнения: неверный адрес памяти или разыменование указателя нулевой точки [сигнал 0xc0000005 code = 0x0 addr = 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     С:/Users/ADMINI~1/AppData/Local/Temp/2/bindist767862039/go/src/pkg/runtime/proc.c: 221 Процесс завершен с кодом выхода 2

Как мне интерпретировать этот код ошибки? Что пошло не так? И как я могу получить JVM startet - он расположен в подкаталоге исполняемого файла Go.

Ответ 1

Обычно рекомендуется, чтобы вы не использовали 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 - это указатель на ноль. Вместо этого вы могли бы сделать attr := new(os.ProcAttr).

Ответ 2

Предыдущие ответы на самом деле не описывают, как использовать 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 (переменные среды).

Ответ 3

Здесь:

var attr* os.ProcAttr

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

Переменная attr равна nil и при разыменовании в os.StartProcess она вызывает ошибку, которую вы видите.