Skip to content

Commit 70478d0

Browse files
committed
cache java types
1 parent d3775d0 commit 70478d0

File tree

4 files changed

+117
-62
lines changed

4 files changed

+117
-62
lines changed

src/javaObject.cpp

Lines changed: 62 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,11 @@
33
#include "java.h"
44
#include "utils.h"
55
#include <sstream>
6+
#include <algorithm>
67

7-
/*static*/ v8::Persistent<v8::FunctionTemplate> JavaObject::s_ct;
8+
std::map<std::string, v8::Persistent<v8::FunctionTemplate> > sFunctionTemplates;
89

910
/*static*/ void JavaObject::Init(v8::Handle<v8::Object> target) {
10-
v8::HandleScope scope;
11-
12-
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
13-
s_ct = v8::Persistent<v8::FunctionTemplate>::New(t);
14-
s_ct->InstanceTemplate()->SetInternalFieldCount(1);
15-
s_ct->SetClassName(v8::String::NewSymbol("JavaObject"));
16-
17-
target->Set(v8::String::NewSymbol("JavaObject"), s_ct->GetFunction());
1811
}
1912

2013
/*static*/ v8::Local<v8::Object> JavaObject::New(Java *java, jobject obj) {
@@ -23,40 +16,71 @@
2316
JNIEnv *env = java->getJavaEnv();
2417
PUSH_LOCAL_JAVA_FRAME();
2518

26-
v8::Local<v8::Function> ctor = s_ct->GetFunction();
27-
v8::Local<v8::Object> javaObjectObj = ctor->NewInstance();
28-
JavaObject *self = new JavaObject(java, obj);
29-
self->Wrap(javaObjectObj);
19+
jclass objClazz = env->GetObjectClass(obj);
20+
jclass classClazz = env->FindClass("java/lang/Class");
21+
jmethodID class_getName = env->GetMethodID(classClazz, "getName", "()Ljava/lang/String;");
22+
jobject classNameJava = env->CallObjectMethod(objClazz, class_getName);
23+
std::string className = javaObjectToString(env, classNameJava);
24+
std::replace(className.begin(), className.end(), '.', '_');
25+
std::replace(className.begin(), className.end(), '$', '_');
26+
std::replace(className.begin(), className.end(), '[', 'a');
27+
className = "nodeJava_" + className;
28+
29+
v8::Persistent<v8::FunctionTemplate> persistentFuncTemplate;
30+
if(sFunctionTemplates.find(className) != sFunctionTemplates.end()) {
31+
//printf("existing className: %s\n", className.c_str());
32+
persistentFuncTemplate = sFunctionTemplates[className];
33+
} else {
34+
//printf("create className: %s\n", className.c_str());
35+
36+
v8::Local<v8::FunctionTemplate> funcTemplate = v8::FunctionTemplate::New();
37+
funcTemplate->InstanceTemplate()->SetInternalFieldCount(1);
38+
funcTemplate->SetClassName(v8::String::NewSymbol(className.c_str()));
39+
40+
std::list<jobject> methods;
41+
javaReflectionGetMethods(env, objClazz, &methods, false);
42+
jclass methodClazz = env->FindClass("java/lang/reflect/Method");
43+
jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;");
44+
for(std::list<jobject>::iterator it = methods.begin(); it != methods.end(); it++) {
45+
jstring methodNameJava = (jstring)env->CallObjectMethod(*it, method_getName);
46+
std::string methodNameStr = javaToString(env, methodNameJava);
47+
48+
v8::Handle<v8::String> methodName = v8::String::New(methodNameStr.c_str());
49+
v8::Local<v8::FunctionTemplate> methodCallTemplate = v8::FunctionTemplate::New(methodCall, methodName);
50+
funcTemplate->PrototypeTemplate()->Set(methodName, methodCallTemplate->GetFunction());
51+
52+
v8::Handle<v8::String> methodNameSync = v8::String::New((methodNameStr + "Sync").c_str());
53+
v8::Local<v8::FunctionTemplate> methodCallSyncTemplate = v8::FunctionTemplate::New(methodCallSync, methodName);
54+
funcTemplate->PrototypeTemplate()->Set(methodNameSync, methodCallSyncTemplate->GetFunction());
55+
56+
env->DeleteLocalRef(methodNameJava);
57+
env->DeleteLocalRef(*it);
58+
}
3059

31-
std::list<jobject> methods;
32-
javaReflectionGetMethods(env, self->m_class, &methods, false);
33-
jclass methodClazz = env->FindClass("java/lang/reflect/Method");
34-
jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;");
35-
for(std::list<jobject>::iterator it = methods.begin(); it != methods.end(); it++) {
36-
jstring methodNameJava = (jstring)env->CallObjectMethod(*it, method_getName);
37-
std::string methodNameStr = javaToString(env, methodNameJava);
38-
39-
v8::Handle<v8::String> methodName = v8::String::New(methodNameStr.c_str());
40-
v8::Local<v8::FunctionTemplate> methodCallTemplate = v8::FunctionTemplate::New(methodCall, methodName);
41-
javaObjectObj->Set(methodName, methodCallTemplate->GetFunction());
42-
43-
v8::Handle<v8::String> methodNameSync = v8::String::New((methodNameStr + "Sync").c_str());
44-
v8::Local<v8::FunctionTemplate> methodCallSyncTemplate = v8::FunctionTemplate::New(methodCallSync, methodName);
45-
javaObjectObj->Set(methodNameSync, methodCallSyncTemplate->GetFunction());
46-
}
60+
std::list<jobject> fields;
61+
javaReflectionGetFields(env, objClazz, &fields);
62+
jclass fieldClazz = env->FindClass("java/lang/reflect/Field");
63+
jmethodID field_getName = env->GetMethodID(fieldClazz, "getName", "()Ljava/lang/String;");
64+
for(std::list<jobject>::iterator it = fields.begin(); it != fields.end(); it++) {
65+
jstring fieldNameJava = (jstring)env->CallObjectMethod(*it, field_getName);
66+
std::string fieldNameStr = javaToString(env, fieldNameJava);
4767

48-
std::list<jobject> fields;
49-
javaReflectionGetFields(env, self->m_class, &fields);
50-
jclass fieldClazz = env->FindClass("java/lang/reflect/Field");
51-
jmethodID field_getName = env->GetMethodID(fieldClazz, "getName", "()Ljava/lang/String;");
52-
for(std::list<jobject>::iterator it = fields.begin(); it != fields.end(); it++) {
53-
jstring fieldNameJava = (jstring)env->CallObjectMethod(*it, field_getName);
54-
std::string fieldNameStr = javaToString(env, fieldNameJava);
68+
v8::Handle<v8::String> fieldName = v8::String::New(fieldNameStr.c_str());
69+
funcTemplate->PrototypeTemplate()->SetAccessor(fieldName, fieldGetter, fieldSetter);
70+
71+
env->DeleteLocalRef(fieldNameJava);
72+
env->DeleteLocalRef(*it);
73+
}
5574

56-
v8::Handle<v8::String> fieldName = v8::String::New(fieldNameStr.c_str());
57-
javaObjectObj->SetAccessor(fieldName, fieldGetter, fieldSetter);
75+
sFunctionTemplates[className] = persistentFuncTemplate = v8::Persistent<v8::FunctionTemplate>::New(funcTemplate);
5876
}
5977

78+
v8::Local<v8::Function> ctor = persistentFuncTemplate->GetFunction();
79+
v8::Local<v8::Object> javaObjectObj = ctor->NewInstance();
80+
javaObjectObj->SetHiddenValue(v8::String::New("__isJavaObject"), v8::Boolean::New(true));
81+
JavaObject *self = new JavaObject(java, obj);
82+
self->Wrap(javaObjectObj);
83+
6084
POP_LOCAL_JAVA_FRAME();
6185

6286
return scope.Close(javaObjectObj);

src/javaObject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <node.h>
77
#include <jni.h>
88
#include <list>
9+
#include <map>
910
#include "methodCallBaton.h"
1011

1112
class Java;
@@ -28,7 +29,6 @@ class JavaObject : public node::ObjectWrap {
2829
static v8::Handle<v8::Value> fieldGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info);
2930
static void fieldSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
3031

31-
static v8::Persistent<v8::FunctionTemplate> s_ct;
3232
Java* m_java;
3333
jobject m_obj;
3434
jclass m_class;

src/utils.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) {
256256

257257
if(arg->IsObject()) {
258258
v8::Local<v8::Object> obj = v8::Object::Cast(*arg);
259-
v8::String::AsciiValue constructorName(obj->GetConstructorName());
260-
if(strcmp(*constructorName, "JavaObject") == 0) {
259+
v8::Local<v8::Value> isJavaObject = obj->GetHiddenValue(v8::String::New("__isJavaObject"));
260+
if(!isJavaObject.IsEmpty() && isJavaObject->IsBoolean()) {
261261
JavaObject* javaObject = node::ObjectWrap::Unwrap<JavaObject>(obj);
262262
jobject jobj = javaObject->getObject();
263263
jclass nodeDynamicProxyClass = env->FindClass("node/NodeDynamicProxyClass");
@@ -310,7 +310,7 @@ jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) {
310310

311311
// TODO: handle other arg types
312312
v8::String::AsciiValue typeStr(arg);
313-
printf("Unhandled type: %s\n", *typeStr);
313+
printf("v8ToJava: Unhandled type: %s\n", *typeStr);
314314
return NULL;
315315
}
316316

@@ -452,7 +452,7 @@ v8::Handle<v8::Value> javaToV8(Java* java, JNIEnv* env, jobject obj) {
452452
case TYPE_OBJECT:
453453
POP_LOCAL_JAVA_FRAME_AND_RETURN(scope.Close(JavaObject::New(java, obj)));
454454
default:
455-
printf("unhandled type: 0x%03x\n", resultType);
455+
printf("javaToV8: unhandled type: 0x%03x\n", resultType);
456456
POP_LOCAL_JAVA_FRAME_AND_RETURN(scope.Close(JavaObject::New(java, obj)));
457457
}
458458

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,74 @@
11
'use strict';
22

3-
//var dbServerName = '';
4-
//var dbPort = 1433;
5-
//var dbName = '';
6-
//var dbUserId = '';
7-
//var dbPassword = '';
8-
//var dbConnectString = 'jdbc:sqlserver://' + dbServerName + ':' + dbPort + ';databaseName=' + dbName + ';selectMethod=direct;responseBuffering=adaptive;packetSize=0;programName=nodeJavaTest;hostProcess=nodeJavaTest;sendStringParametersAsUnicode=false;';
9-
//var dbConnectionClass = 'com.microsoft.sqlserver.jdbc.SQLServerDriver';
3+
var memwatch = require('memwatch');
104

5+
var dbServerName = '192.168.13.190';
6+
var dbPort = 1433;
7+
var dbName = 'test';
118
var dbUserId = 'test';
129
var dbPassword = 'test';
13-
var dbConnectString = "jdbc:mysql://localhost/test";
14-
var dbConnectionClass = 'com.mysql.jdbc.Driver';
10+
var dbConnectString = 'jdbc:sqlserver://' + dbServerName + ':' + dbPort + ';databaseName=' + dbName + ';selectMethod=direct;responseBuffering=adaptive;packetSize=0;programName=nodeJavaTest;hostProcess=nodeJavaTest;sendStringParametersAsUnicode=false;';
11+
var dbConnectionClass = 'com.microsoft.sqlserver.jdbc.SQLServerDriver';
1512

13+
//var dbUserId = 'test';
14+
//var dbPassword = 'test';
15+
//var dbConnectString = "jdbc:mysql://localhost/test";
16+
//var dbConnectionClass = 'com.mysql.jdbc.Driver';
17+
18+
var util = require('util');
1619
var path = require('path');
1720
var java = require('../../');
1821
java.classpath.push(path.join(__dirname, 'sqljdbc4.jar'));
1922
java.classpath.push(path.join(__dirname, 'mysql-connector-java-5.1.22-bin.jar'));
2023
var DriverManager = java.import('java.sql.DriverManager');
2124

22-
for (var loopCount = 0; loopCount < 500000; loopCount++) {
23-
console.log('loopCount:', loopCount);
25+
setTimeout(function() {
26+
console.log('start heap diff');
27+
var hd = new memwatch.HeapDiff();
28+
var loopStart = new Date();
29+
for (var loopCount = 0; loopCount < 10000; loopCount++) {
30+
console.log('loopCount:', loopCount);
31+
doLoop();
32+
}
33+
var loopEnd = new Date();
34+
console.log('end loop', loopEnd - loopStart);
35+
memwatch.gc();
36+
var diff = hd.end();
37+
console.log(util.inspect(diff.change, false, 10, true));
38+
39+
console.log("done... waiting 30seconds");
40+
setTimeout(function() {
41+
console.log("really done");
42+
}, 30 * 1000);
43+
}, 1);
44+
45+
function doLoop() {
2446
java.findClassSync(dbConnectionClass);
2547
var conn = DriverManager.getConnectionSync(dbConnectString, dbUserId, dbPassword);
26-
console.log("connected");
48+
//console.log("connected");
2749
var statement = conn.createStatementSync();
2850
var queryString = "select * from Person";
2951
var rs = statement.executeQuerySync(queryString);
3052
var metaData = rs.getMetaDataSync();
3153
var columnCount = metaData.getColumnCountSync();
3254
while (rs.nextSync()) {
3355
for (var i = 1; i <= columnCount; i++) {
34-
console.log(rs.getObjectSync(i));
56+
var obj = rs.getObjectSync(i);
57+
if (obj) {
58+
if (obj.hasOwnProperty('getClassSync')) {
59+
if (obj.getClassSync().toString() == 'class java.math.BigDecimal') {
60+
//console.log(obj.doubleValueSync());
61+
continue;
62+
}
63+
if (obj.getClassSync().toString() == 'class java.sql.Timestamp') {
64+
//console.log(obj.getTimeSync());
65+
continue;
66+
}
67+
//console.log("class:", obj.getClassSync().toString());
68+
}
69+
//console.log(obj);
70+
}
3571
}
3672
}
3773
conn.closeSync();
38-
}
39-
40-
console.log("done... waiting 30seconds");
41-
setTimeout(function() {
42-
console.log("really done");
43-
}, 30 * 1000);
74+
}

0 commit comments

Comments
 (0)