每日一顶
jsb2.0对于cpp管理js生命周期的对象,处理的有问题。如果用到了spine, box2d等,可能会导致crash(ios,android和win32都可能crash)。修改后最近几天没有crash过了。最近太忙没时间提交pullrequest,有问题的同学可以自己修改下试试(引擎中有多处)。
文档里的
spTrackEntry_setDisposeCallback([](spTrackEntry* entry){ // spTrackEntry 的销毁回调 auto cleanup = [entry](){
if (!se::ScriptEngine::getInstance()->isValid()) return;
se::AutoHandleScope hs; se::ScriptEngine::getInstance()->clearException();
auto iter = se::NativePtrToObjectMap::find(entry); if (iter != se::NativePtrToObjectMap::end()) { CCLOG("spTrackEntry %p was recycled!", entry); se::Object* seObj = iter->second; seObj->clearPrivateData(); // 解除 mapping 关系 seObj->unroot(); // unroot,使 JS 对象受 GC 管理 seObj->decRef(); // 释放 se::Object } };
// 确保不再垃圾回收中去操作 JS 引擎的 API if (!se::ScriptEngine::getInstance()->isGarbageCollecting()) { cleanup(); } else { // 如果在垃圾回收,把清理任务放在帧结束中进行 CleanupTask::pushTaskToAutoReleasePool(cleanup); } });
应该改成类似这样的:
virtual void on_destroyed(void *obj) { auto iter = se::NativePtrToObjectMap::find(obj); if (iter == se::NativePtrToObjectMap::end()) return;
auto seInstance = se::ScriptEngine::getInstance(); if (!seInstance->isValid() || seInstance->isInCleanup()) return;
se::AutoHandleScope hs; seInstance->clearException(); se::Object* seObj = iter->second; seObj->clearPrivateData();
auto cleanup = [seObj]() { auto seInstance = se::ScriptEngine::getInstance(); if (!seInstance->isValid() || seInstance->isInCleanup()) return;
se::AutoHandleScope hs; se::ScriptEngine::getInstance()->clearException();
seObj->unroot(); seObj->decRef(); };
if (!se::ScriptEngine::getInstance()->isGarbageCollecting()) { cleanup(); } else { CleanupTask::pushTaskToAutoReleasePool(cleanup); } }
你这个修复主要是加入了 seInstance->isInCleanup() ?
你碰到的crash问题主要是在热更新重启游戏的时候么?
还有,你吧 clearPrivateData 移动到cleanup 外面是有问题的,因为如果当前是在 GarbageCollecting,操作任何有关JS VM的接口都可能导致问题的。
主要是把clearPrivateData()
放到cleanup()
外面。
不是。cpp控制生命周期的对象,反复创建销毁的时候,会出现assert(NativePtrToObjectMap::find(data) == NativePtrToObjectMap::end());
失败的问题。
如果一个native对象销毁了,但是正在垃圾回收,那么cleanup会被延迟调用。这期间它之前占用的内存可能会被分配给新的对象,这个新的对象在setPrivateData()
的时候就会assert失败。
重现的testcase也很简单,只要重复的“创建native对象,生成相应的SEObject,销毁native对象”就可以了。
这一点我倒是不清楚。不过修改之前是必然crash,修改之后暂时还没crash过。
正在garbage collectiing,是不能操作任何js vm接口,还是只是不能操作clearPrivateData()
?
按我的理解,clearPrivateData()
只是把js obj的private清空而已,并不会导致js obj被回收,理论应该不会有问题才对?而且代码中很多地方都有setPrivateData()
的调用,似乎并没有判断是否正在garbage collecting?
当然我对vm内部不太了解,只是根据相关代码猜测的。
任何有关 JS VM 的包含context接口都不能调用。大部分接口都包含context的。
你反馈的 setPrivateData 触发assert 的确会有问题,这块我考虑一下如何修复更合理。
前面加了se::AutoHandleScope hs;
也不可以的吗?
跟HandleScope没关系。
赞!
有个疑问,在native对象释放后,seobj回收之前,seobj里仍然保留了native对象的指针(野指针),如果js代码恰好在这期间访问了这个对象,会不会crash?
最新1.8.1的安卓有内存泄漏啊,估计是龙骨这块,玩一会儿必定闪退
+1 闪退 卡顿一直存在
嗯,应该。我没继续收到类似反馈。
有问题的可以整理复现方式,我这里会查。
请查收下qq附件 发了一个毕现的崩溃demo
release包 毕现, debug包不崩溃
ios 系统是10.2.1 ipad
xcode:9.2
demo是个jsb-default ios工程
用release的配置Run 就会崩溃
JavaScriptCore JSObjectCallAsFunction + 308
1 JavaScriptCore JSObjectCallAsFunction + 68
2 WinningSlots-mobile __cxa_throw + 484992
3 WinningSlots-mobile __cxa_throw + 491524
4 WinningSlots-mobile __cxa_throw + 2045808
5 WinningSlots-mobile __cxa_throw + 2487704
6 WinningSlots-mobile __cxa_throw + 2572008
7 WinningSlots-mobile __cxa_throw + 1037144
8 JavaScriptCore long long JSC::APICallbackFunction::call<JSC::JSCallbackFunction>(JSC::ExecState*) + 416
9 JavaScriptCore JSC::LLInt::setUpCall(JSC::ExecState*, JSC::Instruction*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*) + 480
10 JavaScriptCore _llint_entry + 24744
11 JavaScriptCore _vmEntryToJavaScript + 264
12 JavaScriptCore JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 168
13 JavaScriptCore JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 352
14 JavaScriptCore JSC::profiledCall(JSC::ExecState*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 160
15 JavaScriptCore JSObjectCallAsFunction + 536
16 WinningSlots-mobile __cxa_throw + 484992
17 WinningSlots-mobile __cxa_throw + 1516060
18 JavaScriptCore long long JSC::APICallbackFunction::call<JSC::JSCallbackFunction>(JSC::ExecState*) + 416
19 JavaScriptCore JSC::LLInt::setUpCall(JSC::ExecState*, JSC::Instruction*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*) + 480
20 JavaScriptCore _llint_entry + 24744
21 JavaScriptCore _llint_entry + 25580
22 JavaScriptCore _llint_entry + 24660
23 JavaScriptCore _llint_entry + 25848
24 JavaScriptCore _llint_entry + 24760
25 JavaScriptCore _llint_entry + 24760
26 JavaScriptCore _llint_entry + 24660
27 JavaScriptCore _llint_entry + 24660
28 JavaScriptCore _llint_entry + 24660
29 JavaScriptCore _llint_entry + 24660
30 JavaScriptCore _vmEntryToJavaScript + 264
31 JavaScriptCore JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 168
32 JavaScriptCore JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 352
33 JavaScriptCore JSC::callSetter(JSC::ExecState*, JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::ECMAMode) + 320
34 JavaScriptCore JSC::JSObject::putInlineSlow(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&) + 2240
35 JavaScriptCore _llint_slow_path_put_by_id + 908
36 JavaScriptCore _llint_entry + 11576
37 JavaScriptCore _llint_entry + 24760
38 JavaScriptCore _llint_entry + 24760
39 JavaScriptCore _llint_entry + 24760
40 JavaScriptCore _llint_entry + 24760
41 JavaScriptCore _llint_entry + 24660
42 JavaScriptCore _llint_entry + 24660
43 JavaScriptCore _vmEntryToJavaScript + 264
44 JavaScriptCore JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 168
45 JavaScriptCore JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 352
46 JavaScriptCore JSC::profiledCall(JSC::ExecState*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 160
47 JavaScriptCore JSObjectCallAsFunction + 536
48 WinningSlots-mobile __cxa_throw + 484992
49 WinningSlots-mobile __cxa_throw + 540888
50 WinningSlots-mobile __cxa_throw + 3068816
51 WinningSlots-mobile __cxa_throw + 3098984
52 WinningSlots-mobile __cxa_throw + 3098824
53 WinningSlots-mobile __cxa_throw + 3082372
54 WinningSlots-mobile __cxa_throw + 3082268
55 WinningSlots-mobile __cxa_throw + 3082628
56 WinningSlots-mobile __cxa_throw + 2393456
57 WinningSlots-mobile __cxa_throw + 2400908
58 QuartzCore CA::Display::DisplayLinkItem::dispatch(unsigned long long) + 44
59 QuartzCore CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 444
60 IOKit IODispatchCalloutFromCFMessage + 372
61 CoreFoundation ___CFMachPortPerform + 180
62 CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
63 CoreFoundation ___CFRunLoopDoSource1 + 436
64 CoreFoundation ___CFRunLoopRun + 1840
65 CoreFoundation CFRunLoopRunSpecific + 444
66 GraphicsServices GSEventRunModal + 180
67 UIKit -[UIApplication _run] + 684
68 UIKit UIApplicationMain + 208
69 WinningSlots-mobile 0x0000000100058000 + 50760
70 libdyld.dylib _start + 4
JavaScriptCore _llint_slow_path_jfalse + 352
1 JavaScriptCore _llint_slow_path_jfalse + 52
2 JavaScriptCore _llint_entry + 23928
3 JavaScriptCore _llint_entry + 26912
4 JavaScriptCore _llint_entry + 26912
5 JavaScriptCore _llint_entry + 26912
6 JavaScriptCore _llint_entry + 26912
7 JavaScriptCore _llint_entry + 26912
8 JavaScriptCore _vmEntryToJavaScript + 272
9 JavaScriptCore JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 184
10 JavaScriptCore JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 400
11 JavaScriptCore JSC::callSetter(JSC::ExecState*, JSC::JSValue, JSC::JSValue, JSC::JSValue, JSC::ECMAMode) + 280
12 JavaScriptCore JSC::JSObject::putInlineSlow(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSC::PutPropertySlot&) + 920
13 JavaScriptCore _llint_slow_path_put_by_id + 880
14 JavaScriptCore _llint_entry + 12112
15 JavaScriptCore _llint_entry + 26912
16 JavaScriptCore _llint_entry + 26912
17 JavaScriptCore _llint_entry + 27012
18 JavaScriptCore _llint_entry + 27012
19 JavaScriptCore _llint_entry + 26912
20 JavaScriptCore _llint_entry + 26912
21 JavaScriptCore _vmEntryToJavaScript + 272
22 JavaScriptCore JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) + 184
23 JavaScriptCore JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 400
24 JavaScriptCore JSC::profiledCall(JSC::ExecState*, JSC::ProfilingReason, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 168
25 JavaScriptCore JSObjectCallAsFunction + 392
26 WinningSlots-mobile __cxa_throw + 484992
27 WinningSlots-mobile __cxa_throw + 540888
28 WinningSlots-mobile __cxa_throw + 3068816
29 WinningSlots-mobile __cxa_throw + 3098984
30 WinningSlots-mobile __cxa_throw + 3098824
31 WinningSlots-mobile __cxa_throw + 3082372
32 WinningSlots-mobile __cxa_throw + 3082268
33 WinningSlots-mobile __cxa_throw + 3082628
34 WinningSlots-mobile __cxa_throw + 2393456
35 WinningSlots-mobile __cxa_throw + 2400908
36 QuartzCore CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 672
37 IOKit IODispatchCalloutFromCFMessage + 392
38 CoreFoundation ___CFMachPortPerform + 188
39 CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56
40 CoreFoundation ___CFRunLoopDoSource1 + 440
41 CoreFoundation ___CFRunLoopRun + 2196
42 CoreFoundation CFRunLoopRunSpecific + 436
43 GraphicsServices GSEventRunModal + 100
44 UIKit UIApplicationMain + 236
45 WinningSlots-mobile 0x0000000102320000 + 50760
46 libdyld.dylib _start + 4
这几个崩溃概率挺高的,在ios上收到了几百个这些崩溃日志。。。具体原因不知道,出现位置也不是必现的,连着手机的时候崩溃过,但都崩在jsc的汇编上了,没有源代码调试。@dumganhar
现在解决了 项目在ios 10.2.1设备 release包必崩溃的问题
如果 jsb里面的接口 如果是 size_t* 类型的 对应的也传 size_t类型的变量地址.
不要用强转(size_t *)
我在c++里面 调用这个接口时候将一个 unsigned int 类型 强转成了 size_t类型 传进去了
debug低概率崩溃 release 必崩溃.
请问大大,这个问题,在1.8.1中解决了吗?
目前我们使用的1.7.2,也是ios频繁闪退,很蛋疼啊,求解救。
能否提供更多的信息协助我们查询问题?
比如给个demo。