Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-24275] Hyperloop: Android - Class not found/Cannot read property 'newInstance' of null (Regression)

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2017-03-09T12:59:43.000+0000
Affected Version/sHyperloop 2.0.0
Fix Version/sHyperloop 2.0.1
ComponentsHyperloop
Labelsandroid, hyperloop, qe-hyperloop, regression
ReporterReymundo López
AssigneeChristopher Williams
Created2017-01-04T23:10:55.000+0000
Updated2017-03-17T21:38:22.000+0000

Description

Same aar is not working in hyperloop 2.0.0 while is working fine in 1.2.8. I have added an aar and setup everything like I did in my native app, this is how the hyperloop file looks like:
var Configuration = require('io.ridetap.Configuration');

var builder = new Configuration.Builder();
Using hyperloop 1.2.8, the code above works without any problem, but starting in hyperloop 2.0.0 it crash saying Class 'io.ridetap.Configuration$Builder' not found. The only differences I see in the generated files for each class is that the path is different: In hyperloop 1.2.8 the call is this: var parentPackage = require('io.ridetap'); while in hyperloop 2.0.0 is this var parentPackage = require('./io.ridetap'); The full log of the error is this:
ERROR] HyperloopUtil: (main) [5188,5188] Class 'io.ridetap.Configuration$Builder' not found
[ERROR] HyperloopUtil: java.lang.ClassNotFoundException: io.ridetap.Configuration$Builder
[ERROR] HyperloopUtil: 	at java.lang.Class.classForName(Native Method)
[ERROR] HyperloopUtil: 	at java.lang.Class.forName(Class.java:400)
[ERROR] HyperloopUtil: 	at java.lang.Class.forName(Class.java:326)
[ERROR] HyperloopUtil: 	at hyperloop.HyperloopModule.getJavaClass(HyperloopModule.java:247)
[ERROR] HyperloopUtil: 	at hyperloop.ProxyFactory.newClass(ProxyFactory.java:81)
[ERROR] HyperloopUtil: 	at hyperloop.HyperloopModule.getClass(HyperloopModule.java:137)
[ERROR] HyperloopUtil: 	at org.appcelerator.kroll.runtime.v8.V8Object.nativeFireEvent(Native Method)
[ERROR] HyperloopUtil: 	at org.appcelerator.kroll.runtime.v8.V8Object.fireEvent(V8Object.java:62)
[ERROR] HyperloopUtil: 	at org.appcelerator.kroll.KrollProxy.doFireEvent(KrollProxy.java:872)
[ERROR] HyperloopUtil: 	at org.appcelerator.kroll.KrollProxy.handleMessage(KrollProxy.java:1095)
[ERROR] HyperloopUtil: 	at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:354)
[ERROR] HyperloopUtil: 	at android.os.Handler.dispatchMessage(Handler.java:98)
[ERROR] HyperloopUtil: 	at android.os.Looper.loop(Looper.java:154)
[ERROR] HyperloopUtil: 	at android.app.ActivityThread.main(ActivityThread.java:6119)
[ERROR] HyperloopUtil: 	at java.lang.reflect.Method.invoke(Native Method)
[ERROR] HyperloopUtil: 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
[ERROR] HyperloopUtil: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
[ERROR] HyperloopUtil: Caused by: java.lang.ClassNotFoundException: Didn't find class "io.ridetap.Configuration$Builder" on path: DexPathList[[zip file "/data/app/com.unosquare.p.moovel.rideTapTest-2/base.apk"],nativeLibraryDirectories=[/data/app/com.unosquare.p.moovel.rideTapTest-2/lib/x86, /system/fake-libs, /data/app/com.unosquare.p.moovel.rideTapTest-2/base.apk!/lib/x86, /system/lib, /vendor/lib]]
[ERROR] HyperloopUtil: 	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
[ERROR] HyperloopUtil: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
[ERROR] HyperloopUtil: 	at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
[ERROR] HyperloopUtil: 	... 17 more
[ERROR] TiExceptionHandler: (main) [11,5199] ----- Titanium Javascript Runtime Error -----
[ERROR] TiExceptionHandler: (main) [0,5199] - In /hyperloop/io.ridetap.Configuration$Builder.js:1,373
[ERROR] TiExceptionHandler: (main) [0,5199] - Message: Uncaught TypeError: Cannot read property 'newInstance' of null
[ERROR] TiExceptionHandler: (main) [0,5199] - Source: (function (exports, require, module, __filename, __dirname, Titanium, Ti, global, kroll) {var Hyperloop=require("hyperloop"),EnclosingClass=require("./io.ridetap.Configuration"),Builder=function(){var e;e=1==arguments.length&&arguments[0].isNativeProxy&&arguments[0].isInstanceProxy&&arguments[0].isInstanceOf("io.ridetap.Configuration$Builder")?arguments[0]:Builder.class.newInstance(arguments),this.$native=e,this._hasPointer=null!=e,this._private={}},SuperClass=require("./java.lang.Object");Builder.prototype=Object.create(SuperClass.prototype),Builder.prototype.constructor=Builder,Object.defineProperty(Builder.prototype,"super",{get:function(){return this._hasPointer?new Builder(this.$native.super):null},enumerable:!0}),Builder.className="io.ridetap.Configuration$Builder",Builder.prototype.className="io.ridetap.Configuration$Builder",Object.defineProperty(Builder,"class",{get:function(){return Hyperloop.getClass("io.ridetap.Configuration$Builder")},enumerable:!0,configurable:!1}),Builder.extend=function(e){var t=Hyperloop.extend("io.ridetap.Configuration$Builder"),n=function(){function n(e){if(e.apiName&&e.isNativeProxy&&e.isInstanceProxy){var t=require("./"+e.apiName);return new t(e)}return e}function r(){for(var e=[],t=0;t<arguments.length;t++)e[t]=n(arguments[t]);return e}var i=t.newInstance(arguments),a=this,o=e,u={};Object.keys(o).forEach(function(e){a[e]=function(){return o[e].apply(a,arguments)},u[e]=function(){return a[e].apply(a,r.apply(this,arguments))}}),i.setOverrides(u),this.$native=i,this._hasPointer=null!=i,this._private={}};return n.prototype=Object.create(Builder.prototype),n.prototype.constructor=n,n},Builder.cast=function(e){return e.$native&&e.$native.isInstanceProxy?new Builder(Hyperloop.cast("io.ridetap.Configuration$Builder",e.$native)):e},Builder.prototype.with=function(){if(!this._hasPointer)return null;var e=this.$native.callNativeFunction({func:"with",instanceMethod:!0,args:Array.prototype.slice.call(arguments)});if(null==e)return null;if(e.apiName){if("io.ridetap.Configuration$Builder"===e.apiName)return new Builder(e);var t=require("./"+e.apiName);return new t(e)}return e},Builder.prototype.setRequiresID=function(){if(!this._hasPointer)return null;var e=this.$native.callNativeFunction({func:"setRequiresID",instanceMethod:!0,args:Array.prototype.slice.call(arguments)});if(null==e)return null;if(e.apiName){if("io.ridetap.Configuration$Builder"===e.apiName)return new Builder(e);var t=require("./"+e.apiName);return new t(e)}return e},Builder.prototype.apiKey=function(){if(!this._hasPointer)return null;var e=this.$native.callNativeFunction({func:"apiKey",instanceMethod:!0,args:Array.prototype.slice.call(arguments)});if(null==e)return null;if(e.apiName){if("io.ridetap.Configuration$Builder"===e.apiName)return new Builder(e);var t=require("./"+e.apiName);return new t(e)}return e},Builder.prototype.setRequiresPayment=function(){if(!this._hasPointer)return null;var e=this.$native.callNativeFunction({func:"setRequiresPayment",instanceMethod:!0,args:Array.prototype.slice.call(arguments)});if(null==e)return null;if(e.apiName){if("io.ridetap.Configuration$Builder"===e.apiName)return new Builder(e);var t=require("./"+e.apiName);return new t(e)}return e},Builder.prototype.setLogLevel=function(){if(!this._hasPointer)return null;var e=this.$native.callNativeFunction({func:"setLogLevel",instanceMethod:!0,args:Array.prototype.slice.call(arguments)});if(null==e)return null;if(e.apiName){if("io.ridetap.Configuration$Builder"===e.apiName)return new Builder(e);var t=require("./"+e.apiName);return new t(e)}return e},Builder.prototype.build=function(){if(!this._hasPointer)return null;var e=this.$native.callNativeFunction({func:"build",instanceMethod:!0,args:Array.prototype.slice.call(arguments)});if(null==e)return null;if(e.apiName){if("io.ridetap.Configuration$Builder"===e.apiName)return new Builder(e);var t=require("./"+e.apiName);return new t(e)}return e},Builder.prototype.setMapMode=function(){if(!this._hasPointer)return null;var e=this.$na
[ERROR] V8Exception: Exception occurred at /hyperloop/io.ridetap.Configuration$Builder.js:1: Uncaught TypeError: Cannot read property 'newInstance' of null
[ERROR] EGL_emulation: tid 7039: eglSurfaceAttrib(1174): error 0x3009 (EGL_BAD_MATCH)

Comments

  1. Christopher Williams 2017-02-16

    Hmm, the underlying issue is a ClassNotFoundException suddenly, which means the JVM can't find the class io.ridetap.Configuration$Builder at runtime. Did the AAR get updated recently and maybe is using a new API? Or perhaps we broke grabbing the jar inside jars somehow? [~reymundolopez] It'd be useful to have a copy of the AAR in question for us to test and reproduce this issue with.
  2. Reymundo López 2017-02-16

    Hey @Chris Williams, is there a way that I can send you the aar in a non public way?.
  3. Christopher Williams 2017-02-17

    [~reymundolopez] You can email it to me at cwilliams@axway.com
  4. Christopher Williams 2017-02-17

    [~reymundolopez] Actually, apparently the corporate mail server decided to filter it out. Please try again at chris.a.williams@gmail.com, thanks!
  5. Reymundo López 2017-02-17

    @Chris Williams no problem, let me send it to you again.
  6. Rodolfo Perottoni 2017-03-01

    It's been 2 months since Hyperloop 2.0.0 was released and no one can use it in Android because of this major bug. Have you ever thought of posting a public note telling people that they are paying 99$ a month for something that doesn't work? Because that would make a lot of sense.
  7. Christopher Williams 2017-03-06

    I'm starting to dive deeper into this, but it's likely not caused by the PR Hans mentioned. Once you decompile the apk's classes you find that the io.ridetap.Configuration and io.ridetap.Configuration$Builder classes aren't in the APK's classes.dex. So the underlying error is right - it can't load a class which isn't there. The question is why this is happening. Maybe multidex is somehow causing it? Maybe the inconspicuous change here is the cause: https://github.com/appcelerator/hyperloop.next/commit/c704f700041b3ea665188c86cf681774320e67d7 ? Not sure, I need to do some more testing...
  8. Christopher Williams 2017-03-07

    OK, narrowed this down. Basically Android will complain if you have identical JARs in the class path/APK. We added a partial implementation of filtering out duplicates. We only check the jar base name and extension. The issue is that if you use multiple AARs, they all just hold a "classes.jar" inside, so there will be clashes using that simple criteria. I had a placeholder TODO to add sha1/size checking as well, but never got around to it. That's the cause of the issue here - the RideTap's classes.jar is getting filtered out as a duplicate because of the classes.jar name clash with another AAR. I guess I need to actually add SHA1/size checks now.
  9. Christopher Williams 2017-03-07

    All right, here's a PR for 2_0_X branch: https://github.com/appcelerator/hyperloop.next/pull/129 I modified the code to basically skip duplicate JAR checks on 'classes.jar' files (since the name is always a clash, due to AARs needing to have this specific filename inside). For other JARs I now check the base name and SHA1 to remove duplicates and/or error out with details on conflicting JARs with the same name and different hash (asking the user to delete or rename one to resolve it manually).
  10. Christopher Williams 2017-03-07

    https://github.com/appcelerator/hyperloop.next/pull/129
  11. Hans Knöchel 2017-03-08

    PR (master): https://github.com/appcelerator/hyperloop.next/pull/130
  12. Jerod Fritz 2017-03-12

    Also having this same issue. Worked fine with Hyperloop <2.0 now java.lang.ClassNotFoundException . Mine is for var Intercom = require("io.intercom.android.sdk.Intercom"); How do we install Hyperloop 2.0.1 manually to test your resolution?
  13. Hans Knöchel 2017-03-12

    [~jerodfritz] Hyperloop 2.0.1 will be pushed together with SDK 6.0.3 next week on Friday.
  14. Abir Mukherjee 2017-03-15

    [~hansknoechel] Samir and I tried this using Hyperloop 2.0.0. and 2.0.1 and saw the same behavior. We saw the splash screen, but no errors or crash. Can you please let us know whether we ran the test correctly. We were expecting to reproduce the bug using 2.0.0, but didn't. We added 2 files to platform/android and used the two-line demo code in app.js.
  15. Josh Longton 2017-03-17

    Verified as fixed, Classes are now found and ./ before a module is no longer required. Tested on: {noformat} macOS Sierra 10.12.3 Pixel Xl (7.1.1) android emulator (4.4.2, 6.0) Ti SDK: 6.0.3.v20170317093820 Hyperloop: 2.0.1 Appc CLI: 6.1.0 Appc NPM: 4.2.9-1 Node v4.6.0 {noformat} *Closing Ticket.*

JSON Source