Skip to content

Commit 397cf61

Browse files
authored
Remove usage of deprecated DexFile api (#1438)
* Remove deprecated DexFile api * Address comments of code review
1 parent d3d6470 commit 397cf61

File tree

15 files changed

+494
-125
lines changed

15 files changed

+494
-125
lines changed

test-app/app/build.gradle

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@
1818
* -PandroidXMaterial=[androidx_material_version]
1919
*/
2020

21+
22+
import groovy.io.FileType
2123
import groovy.json.JsonSlurper
24+
25+
import javax.inject.Inject
2226
import java.nio.file.Files
2327
import java.nio.file.Paths
2428
import java.nio.file.StandardCopyOption
25-
import groovy.io.FileType
2629
import java.security.MessageDigest
27-
import javax.inject.Inject
30+
2831
apply plugin: "com.android.application"
2932

3033
def onlyX86 = project.hasProperty("onlyX86")
@@ -545,7 +548,7 @@ afterEvaluate { project ->
545548
// if there's a project dependency search for its result jar file in the build/intermediates/runtime_library_classes folder
546549
// this is the output folder in gradle 5.1.1, but it can be changed in the future versions of gradle
547550
def jarDir = new File("${it.getBuildDir()}/intermediates/runtime_library_classes/${buildType.toLowerCase()}")
548-
if(jarDir.exists()) {
551+
if (jarDir.exists()) {
549552
jarDir.eachFileRecurse(FileType.FILES) { file ->
550553
if (file.path.endsWith(".jar")) {
551554
processJar(file, jars)
@@ -574,7 +577,7 @@ def processJar(File jar, jars) {
574577
// directory is a randomly generated string)
575578
cleanupAllJars.inputs.files jar
576579

577-
task "${taskName}" (type: WorkerTask) {
580+
task "${taskName}"(type: WorkerTask) {
578581
dependsOn cleanupAllJars
579582
extractAllJars.dependsOn it
580583

test-app/app/src/main/assets/app/tests/testsForRuntimeBindingGenerator.js

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,20 @@ describe("Tests for runtime binding generator", function () {
4949
expect(isInstanceOf).toEqual(true);
5050
});
5151

52-
it("When_implementing_interface_and_its_implemented_interfaces", function() {
53-
var impl = new com.tns.tests.MyDerivedPublicInterface({
54-
methodOfMyDerivedPublicInterface: function(input) {
55-
return "Le java " + input;
56-
},
57-
methodOfMyPublicInterface: function(input) {
58-
return "Le java " + input;
59-
}
60-
});
61-
62-
try {
63-
var C = java.lang.Class.forName("com.tns.gen.com.tns.tests.MyDerivedPublicInterface");
64-
expect(C).not.toBe(null);
65-
66-
var expected = "Le java test derived method";
67-
var actual = impl.methodOfMyPublicInterface("test derived method");
68-
expect(actual).toBe(expected);
69-
} catch (e) {
70-
//fail("class was not found");
71-
expect(true).toBe(false);
72-
}
73-
});
52+
it("When_implementing_interface_and_its_implemented_interfaces", function() {
53+
var impl = new com.tns.tests.MyDerivedPublicInterface({
54+
methodOfMyDerivedPublicInterface: function(input) {
55+
return "Le java " + input;
56+
},
57+
methodOfMyPublicInterface: function(input) {
58+
return "Le java " + input;
59+
}
60+
});
61+
62+
var expected = "Le java test derived method";
63+
var actual = impl.methodOfMyPublicInterface("test derived method");
64+
expect(actual).toBe(expected);
65+
});
7466

7567
it("When_generating_a_class_that_implements_interfaces_javascript", function() {
7668

test-app/runtime/src/main/java/com/tns/ClassResolver.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package com.tns;
22

3+
import com.tns.system.classes.loading.ClassStorageService;
4+
35
import java.io.IOException;
46

57
class ClassResolver {
6-
private final Runtime runtime;
8+
private final ClassStorageService classStorageService;
79

8-
public ClassResolver(Runtime runtime) {
9-
this.runtime = runtime;
10+
ClassResolver(ClassStorageService classStorageService) {
11+
this.classStorageService = classStorageService;
1012
}
1113

12-
public Class<?> resolveClass(String baseClassName, String fullClassName, DexFactory dexFactory, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
14+
Class<?> resolveClass(String baseClassName, String fullClassName, DexFactory dexFactory, String[] methodOverrides, String[] implementedInterfaces, boolean isInterface) throws ClassNotFoundException, IOException {
1315
String canonicalClassName = fullClassName.replace('/', '.');
1416
String canonicalBaseClassName = baseClassName.replace('/', '.');
1517
String name = "";
@@ -24,7 +26,7 @@ public Class<?> resolveClass(String baseClassName, String fullClassName, DexFact
2426
}
2527

2628
if (clazz == null) {
27-
clazz = Runtime.getClassForName(className);
29+
clazz = classStorageService.retrieveClass(className);
2830
}
2931

3032
return clazz;

test-app/runtime/src/main/java/com/tns/DexFactory.java

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
import android.util.Log;
44

5+
import com.tns.bindings.AnnotationDescriptor;
6+
import com.tns.bindings.ProxyGenerator;
7+
import com.tns.bindings.desc.ClassDescriptor;
8+
import com.tns.bindings.desc.reflection.ClassInfo;
9+
import com.tns.system.classes.loading.ClassStorageService;
10+
511
import java.io.BufferedReader;
612
import java.io.BufferedWriter;
713
import java.io.File;
@@ -12,18 +18,11 @@
1218
import java.io.InputStreamReader;
1319
import java.io.InvalidClassException;
1420
import java.io.OutputStreamWriter;
15-
import java.util.ArrayList;
1621
import java.util.HashMap;
1722
import java.util.HashSet;
18-
import java.util.List;
1923
import java.util.zip.ZipEntry;
2024
import java.util.zip.ZipOutputStream;
2125

22-
import com.tns.bindings.AnnotationDescriptor;
23-
import com.tns.bindings.ProxyGenerator;
24-
import com.tns.bindings.desc.ClassDescriptor;
25-
import com.tns.bindings.desc.reflection.ClassInfo;
26-
2726
import dalvik.system.DexClassLoader;
2827

2928
public class DexFactory {
@@ -34,11 +33,12 @@ public class DexFactory {
3433
private final File odexDir;
3534
private final String dexThumb;
3635
private final ClassLoader classLoader;
36+
private final ClassStorageService classStorageService;
3737

3838
private ProxyGenerator proxyGenerator;
3939
private HashMap<String, Class<?>> injectedDexClasses = new HashMap<String, Class<?>>();
4040

41-
public DexFactory(Logger logger, ClassLoader classLoader, File dexBaseDir, String dexThumb) {
41+
DexFactory(Logger logger, ClassLoader classLoader, File dexBaseDir, String dexThumb, ClassStorageService classStorageService) {
4242
this.logger = logger;
4343
this.classLoader = classLoader;
4444
this.dexDir = dexBaseDir;
@@ -58,6 +58,7 @@ public DexFactory(Logger logger, ClassLoader classLoader, File dexBaseDir, Strin
5858

5959
this.updateDexThumbAndPurgeCache();
6060
this.proxyGenerator.setProxyThumb(this.dexThumb);
61+
this.classStorageService = classStorageService;
6162
}
6263

6364
static long totalGenTime = 0;
@@ -154,36 +155,17 @@ public Class<?> resolveClass(String baseClassName, String name, String className
154155
out.closeEntry();
155156
out.close();
156157
}
157-
//
158158

159-
Class<?> result = null;
160-
try {
161-
// use DexFile instead of DexClassLoader to allow class loading
162-
// within the default class loader
163-
// Note: According to the official documentation, DexFile should not
164-
// be directly used.
165-
// However, this is the only viable way to get our dynamic classes
166-
// loaded within the system class loader
159+
Class<?> result;
160+
DexClassLoader dexClassLoader = new DexClassLoader(jarFilePath, this.odexDir.getAbsolutePath(), null, classLoader);
167161

168-
if (isInterface) {
169-
@SuppressWarnings("deprecation")
170-
dalvik.system.DexFile df = dalvik.system.DexFile.loadDex(jarFilePath, new File(this.odexDir, fullClassName).getAbsolutePath(), 0);
171-
result = df.loadClass(fullClassName, classLoader);
172-
} else {
173-
@SuppressWarnings("deprecation")
174-
dalvik.system.DexFile df = dalvik.system.DexFile.loadDex(jarFilePath, new File(this.odexDir, desiredDexClassName).getAbsolutePath(), 0);
175-
result = df.loadClass(desiredDexClassName, classLoader);
176-
}
177-
} catch (IOException e) {
178-
Log.w("JS", String.format("Error resolving class %s: %s. Fall back to DexClassLoader."));
179-
if (com.tns.Runtime.isDebuggable()) {
180-
e.printStackTrace();
181-
}
182-
// fall back to DexClassLoader
183-
DexClassLoader dexClassLoader = new DexClassLoader(jarFilePath, this.odexDir.getAbsolutePath(), null, classLoader);
162+
if (isInterface) {
184163
result = dexClassLoader.loadClass(fullClassName);
164+
} else {
165+
result = dexClassLoader.loadClass(desiredDexClassName);
185166
}
186167

168+
classStorageService.storeClass(result.getName(), result);
187169
this.injectedDexClasses.put(originalFullClassName, result);
188170

189171
return result;

0 commit comments

Comments
 (0)