Skip to content

Commit

Permalink
Remove usage of non-public value field (#1434)
Browse files Browse the repository at this point in the history
  • Loading branch information
vmutafov committed Aug 1, 2019
1 parent af31471 commit 65e503c
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 116 deletions.
35 changes: 18 additions & 17 deletions test-app/runtime/src/main/cpp/JType.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "JType.h"
#include "NativeScriptAssert.h"

namespace tns {
Type JType::getClassType(int retType) {
Expand Down Expand Up @@ -48,42 +49,42 @@ jobject JType::NewDouble(JEnv env, jdouble value) {

jbyte JType::ByteValue(JEnv env, jobject value) {
EnsureInstance(env, &Byte, Type::Byte);
return env.GetByteField(value, Byte->valueField);
return env.CallByteMethod(value, Byte->valueMethodId);
}

jchar JType::CharValue(JEnv env, jobject value) {
EnsureInstance(env, &Char, Type::Char);
return env.GetCharField(value, Char->valueField);
return env.CallCharMethod(value, Char->valueMethodId);
}

jboolean JType::BooleanValue(JEnv env, jobject value) {
EnsureInstance(env, &Boolean, Type::Boolean);
return env.GetBooleanField(value, Boolean->valueField);
return env.CallBooleanMethod(value, Boolean->valueMethodId);
}

jshort JType::ShortValue(JEnv env, jobject value) {
EnsureInstance(env, &Short, Type::Short);
return env.GetShortField(value, Short->valueField);
return env.CallShortMethod(value, Short->valueMethodId);
}

jint JType::IntValue(JEnv env, jobject value) {
EnsureInstance(env, &Int, Type::Int);
return env.GetIntField(value, Int->valueField);
return env.CallIntMethod(value, Int->valueMethodId);
}

jlong JType::LongValue(JEnv env, jobject value) {
EnsureInstance(env, &Long, Type::Long);
return env.GetLongField(value, Long->valueField);
return env.CallLongMethod(value, Long->valueMethodId);
}

jfloat JType::FloatValue(JEnv env, jobject value) {
EnsureInstance(env, &Float, Type::Float);
return env.GetFloatField(value, Float->valueField);
return env.CallFloatMethod(value, Float->valueMethodId);
}

jdouble JType::DoubleValue(JEnv env, jobject value) {
EnsureInstance(env, &Double, Type::Double);
return env.GetDoubleField(value, Double->valueField);
return env.CallDoubleMethod(value, Double->valueMethodId);
}

void JType::EnsureInstance(JEnv env, JType** instance, Type type) {
Expand All @@ -92,51 +93,51 @@ void JType::EnsureInstance(JEnv env, JType** instance, Type type) {
}

*instance = new JType();

(*instance)->Init(env, type);
}

void JType::Init(JEnv env, Type type) {
// TODO: Provide a fallback mechanism to prevent possible field name changes
switch (type) {
case Type::Byte:
this->clazz = env.FindClass("java/lang/Byte");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(B)V");
this->valueField = env.GetFieldID(this->clazz, "value", "B");
this->valueMethodId = env.GetMethodID(this->clazz, "byteValue", "()B");
break;
case Type::Char:
this->clazz = env.FindClass("java/lang/Character");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(C)V");
this->valueField = env.GetFieldID(this->clazz, "value", "C");
this->valueMethodId = env.GetMethodID(this->clazz, "charValue", "()C");
break;
case Type::Boolean:
this->clazz = env.FindClass("java/lang/Boolean");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(Z)V");
this->valueField = env.GetFieldID(this->clazz, "value", "Z");
this->valueMethodId = env.GetMethodID(this->clazz, "booleanValue", "()Z");
break;
case Type::Short:
this->clazz = env.FindClass("java/lang/Short");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(S)V");
this->valueField = env.GetFieldID(this->clazz, "value", "S");
this->valueMethodId = env.GetMethodID(this->clazz, "shortValue", "()S");
break;
case Type::Int:
this->clazz = env.FindClass("java/lang/Integer");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(I)V");
this->valueField = env.GetFieldID(this->clazz, "value", "I");
this->valueMethodId = env.GetMethodID(this->clazz, "intValue", "()I");
break;
case Type::Long:
this->clazz = env.FindClass("java/lang/Long");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(J)V");
this->valueField = env.GetFieldID(this->clazz, "value", "J");
this->valueMethodId = env.GetMethodID(this->clazz, "longValue", "()J");
break;
case Type::Float:
this->clazz = env.FindClass("java/lang/Float");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(F)V");
this->valueField = env.GetFieldID(this->clazz, "value", "F");
this->valueMethodId = env.GetMethodID(this->clazz, "floatValue", "()F");
break;
case Type::Double:
this->clazz = env.FindClass("java/lang/Double");
this->ctor = env.GetMethodID(this->clazz, "<init>", "(D)V");
this->valueField = env.GetFieldID(this->clazz, "value", "D");
this->valueMethodId = env.GetMethodID(this->clazz, "doubleValue", "()D");
break;
default:
break;
Expand Down
2 changes: 1 addition & 1 deletion test-app/runtime/src/main/cpp/JType.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class JType {

jclass clazz;
jmethodID ctor;
jfieldID valueField;
jmethodID valueMethodId;

static JType* Byte;
static JType* Char;
Expand Down
12 changes: 7 additions & 5 deletions test-app/runtime/src/main/java/com/tns/ClassResolver.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.tns;

import com.tns.system.classes.loading.ClassStorageService;

import java.io.IOException;

class ClassResolver {
private final Runtime runtime;
private final ClassStorageService classStorageService;

public ClassResolver(Runtime runtime) {
this.runtime = runtime;
ClassResolver(ClassStorageService classStorageService) {
this.classStorageService = classStorageService;
}

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

if (clazz == null) {
clazz = Runtime.getClassForName(className);
clazz = classStorageService.retrieveClass(className);
}

return clazz;
Expand Down
47 changes: 15 additions & 32 deletions test-app/runtime/src/main/java/com/tns/DexFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

import android.util.Log;

import com.tns.bindings.AnnotationDescriptor;
import com.tns.bindings.ProxyGenerator;
import com.tns.bindings.desc.ClassDescriptor;
import com.tns.bindings.desc.reflection.ClassInfo;
import com.tns.system.classes.loading.ClassStorageService;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
Expand All @@ -12,18 +18,11 @@
import java.io.InputStreamReader;
import java.io.InvalidClassException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.tns.bindings.AnnotationDescriptor;
import com.tns.bindings.ProxyGenerator;
import com.tns.bindings.desc.ClassDescriptor;
import com.tns.bindings.desc.reflection.ClassInfo;

import dalvik.system.DexClassLoader;

public class DexFactory {
Expand All @@ -34,11 +33,12 @@ public class DexFactory {
private final File odexDir;
private final String dexThumb;
private final ClassLoader classLoader;
private final ClassStorageService classStorageService;

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

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

this.updateDexThumbAndPurgeCache();
this.proxyGenerator.setProxyThumb(this.dexThumb);
this.classStorageService = classStorageService;
}

static long totalGenTime = 0;
Expand Down Expand Up @@ -154,36 +155,18 @@ public Class<?> resolveClass(String baseClassName, String name, String className
out.closeEntry();
out.close();
}
//

Class<?> result = null;
try {
// use DexFile instead of DexClassLoader to allow class loading
// within the default class loader
// Note: According to the official documentation, DexFile should not
// be directly used.
// However, this is the only viable way to get our dynamic classes
// loaded within the system class loader
Class<?> result;

if (isInterface) {
@SuppressWarnings("deprecation")
dalvik.system.DexFile df = dalvik.system.DexFile.loadDex(jarFilePath, new File(this.odexDir, fullClassName).getAbsolutePath(), 0);
result = df.loadClass(fullClassName, classLoader);
} else {
@SuppressWarnings("deprecation")
dalvik.system.DexFile df = dalvik.system.DexFile.loadDex(jarFilePath, new File(this.odexDir, desiredDexClassName).getAbsolutePath(), 0);
result = df.loadClass(desiredDexClassName, classLoader);
}
} catch (IOException e) {
Log.w("JS", String.format("Error resolving class %s: %s. Fall back to DexClassLoader."));
if (com.tns.Runtime.isDebuggable()) {
e.printStackTrace();
}
// fall back to DexClassLoader
if (isInterface) {
DexClassLoader dexClassLoader = new DexClassLoader(jarFilePath, this.odexDir.getAbsolutePath(), null, classLoader);
result = dexClassLoader.loadClass(fullClassName);
} else {
DexClassLoader dexClassLoader = new DexClassLoader(jarFilePath, this.odexDir.getAbsolutePath(), null, classLoader);
result = dexClassLoader.loadClass(desiredDexClassName);
}

classStorageService.storeClass(result.getName(), result);
this.injectedDexClasses.put(originalFullClassName, result);

return result;
Expand Down
Loading

0 comments on commit 65e503c

Please sign in to comment.