Monday, June 1, 2020

Runtime Class for Android

Runtime Class for Android

Porting the JRebel standard core to Android has some major challenges. For example, the service component has to know the full class path up front to enable processing of all classes before they are sent to the device. Also, given the fact that system classes in general cannot be altered before loading, means that all of the hooks for handling reflection, serialization, dynamic proxies, hiding JRebel artifacts from the stacktrace to name a few, cannot be installed. For this reason JRebel.Android instead injects client-side hooks to method calls to specific methods within system classes, enabling enhanced behavior. This is quite effective, but works only when called from application classes and the set of libraries, for which the service component must also locate each one for installing the said client-side hooks. In the past decade more advanced class reloading capabilities have been proposed and to a large extent adopted by the Java community. Leading the pack currently is the commercial redeployment tool JRebel [8], which were recently enhanced with the capabilities brought in by the technology developed for Javeleon, [6]. DCEVM constitutes a completely different approach to class reloading in Java in the sense that it operates at the JVM-level enhancing the current HotSwap mechanism to allow arbitrary changes to code at runtime. Unfortunately, it does not work on all JVM’s and moreover requires the user to patch the JDK installation. In addition, DCEVM has no support for the Android platform whatsoever. To the best of our knowledge the only tool that does have some class reloading support for Android is Insta Reloader, [7]. It supports adding/removing method, fields and classes, but it does not support changes to constructors as JRebel.Android does. Also, the Reflection API is not properly supported meaning that synthetically added members will show up in ntrospection results, and new members cannot be found through reflection at all. Insta Reloader has some support for reloading resources, but from simple tests notable issues were observed. Also, in contrast to JRebel.Android, Insta Reloader leaves generated artifacts inside the Android manifest file, which will pollute production code
codeshoppy
JRebel.Android has two components – agent running on an Android device and service running on the host (developer’s machine). The primary responsibility of the service component is to watch for changes in the classes and resources directories. Upon finding changes to files the service component prepares them for later reloads by transforming the bytecode according to JRebel’s inner workings and sends them to the agent, telling the agent to perform a reload task. Whenever the agent component receives the files from the service component, it triggers the runtime reloading operation, thus making the offline changes that were picked up by the service component active on the device. The tool is designed with ease of use in mind, so the only required input parameter for the service is the root directory of an Android project. Given this directory the service component automatically locates the Android manifest file, class and resource directories as well as any external libraries and project dependencies. Typically one of two build systems are used when developing Android applications, that being Ant or Gradle. JRebel.Android supports both layouts, and there is even support for some custom project layouts built-in. The first time the service component is started for a given target Android project, it utilizes the Android Debug Bridge (ADB), [3] connection to install the agent as part of the existing Android application. For all subsequent runs, having an ADB connection available is optional. The only requirement thereafter is that the agent is either reachable by ADB or through the network somehow. Again, this is a clear sign of the ease-of-use design principle taken for JRebel.Android, given that it is not always be desirable to test Android applications on physical devices using cables, if the nature of the application requires the user to e.g. move around, or rotate the device a lot. Every time the service component starts up it transforms the bytecode of all classes, prepares resources and sends them to the agent now installed on the device. Upon receiving the preprocessed files the agent component restarts the underlying application now using the reload-enabled files. In order to make reload operations fast, the service component only processes changed files, meaning that the files sent to the agent component for reloads are small.
Initialize the connection and perform verification of the specific agent version expected by the service. Keep-alive – keep an idle connection to detect disconnection. In case of disconnects and later reconnects, the ‘Report’ command is used, in order to determine if the current state of the agent complies with that of the service. Load – send initial instrumented application package and restart the application using it. Add-metadata – send metadata about classes to enable reloading. Reload – send the new classes/resources and activate them. Report – the service requests the state of the agent to determine if they are in sync. If yes, the service starts watching for file changes. If not, the service will restart. To reload resources of an Android application we replace the original resource loading logic with our own. We keep primitive values in our own memory-based registry and load XML files from a custom directory. On service side if any resource is changed we scan the files to update this registry. We also use the registry to resolve all references to those values in the XML files. Finally, we compile the resource files using the aapt-tool and send the files along with the serialized registry data to the agent. The agent then just updates the local registry and files. To refresh the UI state we also recreate the current activity.
 Runtime Class for Android
In this section we report on the redeploy times of Android application development on the chosen sample applications with and without JRebel.Android. The redeploy time without JRebel.Android is measured from the time where the developer presses the run button in the IDE, which triggers reinstallation on the device. For these experiments a Google Nexus 5 phone was used. The redeploy time with JRebel.Android is the time taken from when the tool detects a class file change (using OS file system notifications) until the change is reflected on the device. The tool automatically writes this time to system output during normal operation. Table 1. shows the measured redeploy times. All numbers are simple averages based on at least 10 samples. Numbers were very similar for each sample, so improving the statistic validity of the measurements had a low priority for this paper.


No comments:

Post a Comment