forked from abneptis/GoJVM
/
jvm.c.go
115 lines (103 loc) · 2.93 KB
/
jvm.c.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package gojvm
//#include "helpers.h"
import "C"
import (
"errors"
"github.com/timob/gojvm/types"
"strings"
"unsafe"
"runtime"
)
type JVM struct {
jvm *C.JavaVM
registered map[int]callbackDescriptor
regId int
}
func (self *JVM) addNative(env *Environment, f interface{}) (id int, csig types.MethodSignature, err error) {
//func CallbackSignature(f interface{})(sig MethodSignature, err error){
cbd, err := CallbackDescriptor(env, f)
if err != nil {
return
}
/// todo, this is not thread safe...
id = self.regId
self.registered[id] = cbd
self.regId++
csig = cbd.Signature
//log.Printf("Calculated signature: %v", csig)
/// TODO
return
}
/*
Returns a new environment pointer that is appropriate for the /currently executing/
thread to use. It is safe to call multiply (idempotent), and can be returned
via DetachCurrentThread (not idempotent!)
*/
func (self *JVM) AttachCurrentThread() (env *Environment, err error) {
env = NewEnvironment(self)
runtime.LockOSThread()
//print ("Allocated environment for thread\t", env.Ptr(),"\n")
if 0 != C.vmAttachCurrentThread(self.jvm, env.Ptr(), nil) {
err = errors.New("Couldn't attach thread (and thus cannot gather exception)")
} else {
AllEnvs.Add(env)
}
return
}
// notifies the JVM of your threads done-ness w/ it, and deallocates the associated
// environment pointer. Depending on the exact JDK version, there are differing semantics
// on whether the 'original' thread can call this (else JVM Shutdown), but most modern
// stacks (>=1.2) should allow this from the 'main' thread.
func (self *JVM) DetachCurrentThread() (err error) {
if 0 != C.vmDetachCurrentThread(self.jvm) {
err = errors.New("Couldn't attach thread (and thus cannot gather exception)")
}
return
}
type JvmConfig struct {
ClassPath []string
}
func NewJVM(ver int, conf JvmConfig) (jvm *JVM, env *Environment, err error) {
runtime.LockOSThread()
args, err := defaultJVMArgs(ver)
if err != nil {
return
}
pathStr := strings.Join(conf.ClassPath, ":")
//print("Adding class path\n")
err = addStringArg(args, "-Djava.class.path="+pathStr)
if err == nil {
//print("Initializing JVM Context\n")
jvm = &JVM{
registered: map[int]callbackDescriptor{},
}
env = NewEnvironment(jvm)
if 0 != C.newJVMContext(&jvm.jvm, env.Ptr(), args) {
err = errors.New("Couldn't instantiate JVM")
} else {
AllVMs.Add(jvm)
}
}
return
}
func defaultJVMArgs(ver int) (args *C.JavaVMInitArgs, err error) {
if ver == 0 {
ver = DEFAULT_JVM_VERSION
}
args = new(C.JavaVMInitArgs)
//print("Default args\t", ver,"\n")
args.version = C.jint(ver)
if 0 != C.JNI_GetDefaultJavaVMInitArgs(unsafe.Pointer(args)) {
err = errors.New("Couldn't contruct default JVM args")
}
return
}
func addStringArg(args *C.JavaVMInitArgs, s string) (err error) {
cstr := C.CString(s)
defer C.free(unsafe.Pointer(cstr))
ok := C.addStringArgument(args, cstr)
if ok != 0 {
err = errors.New("addStringArg failed")
}
return
}