android 从jobject、jclass获取类名(API>19)(一)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android 从jobject、jclass获取类名(API>19)(一)相关的知识,希望对你有一定的参考价值。
参考技术A 用途在Art中Hook JNI相关函数。存在jobject jclass 参数时需要得到具体的类名。在Art虚拟机中:
jobject在内存中表现为:art::mirror::Object,可从GetObjectClass方法中分析得到(art/runtime/jni_internal.cc)
jclass在内存中表现为:art::mirror::Class,可从GetSuperclass方法中分析得到(art/runtime/jni_internal.cc)
获取类名重点在art::mirror::Class类中,通过分析Class 类发现在art/runtime/mirror/class-inl.h头文件中存在一个获取类名的方法
上述方法存在两个问题:
综上所述,GetName不适合获取类名
在dalvik虚拟机中存在一个方法dvmDecodeIndirectRef,可以将jobject、jclass转为对应的内存结构指针。
经过查找发现在/art/runtime/thread.cc中存在一个方法DecodeJObject可以将jobject、jclass转换为对应的内存结构指针
DecodeJObject是Thread类的一个方法,通过dlsym拿到方法地址后,其表现形式如下:
第一个参数表示this即当前对象。可以通过如下方法获取Thread对象的实例
同时发现/art/runtime/mirror/class.cc中存在GetDescriptor方法可以获取art::mirror::Class的类名
GetDescriptor是Class类的一个方法,通过dlsym拿到方法地址后,其表现形式如下:
第一个参数表示this即当前对象。可以通过DecodeJObject获取Class对象的实例,
在最终可以整理得到获取jclass类名的方法:
获取jobject方法就简单一点其内存结构可以精简如下:
其中klass就是Class对象的指针,最终整理后的方法如下:
上述方法太过于麻烦,后面给出一个简单的方法,可以模拟dalvik解析dex拿到类名。不早了,睡了
如何在不添加新 JObject 键/名称的情况下将 JArray 添加到 JObject 中?
【中文标题】如何在不添加新 JObject 键/名称的情况下将 JArray 添加到 JObject 中?【英文标题】:How would you add a JArray into a JObject without adding a new JObject key/name? 【发布时间】:2021-12-18 19:20:11 【问题描述】:使用 .NET C#,我正在尝试从 JArray 创建一个新的 JObject。我有一个 FetchData JObject,我想返回一个数据 JObject 以进行数据驱动测试。这是我目前所拥有的:
public static JObject FetchData(string testMethodName)
using (StreamReader r = new StreamReader("PathToJsonfile"))
string jsonstring = r.ReadToEnd();
JObject obj = JObject.Parse(jsonstring);
JArray jsonArray = JArray.Parse(obj[testMethodName].ToString());
JObject jObject = new JObject(new JProperty("test",jsonArray));
return jObject;
我想返回一个与正在运行的 testMethod 相关的测试数据的 JObject。当我运行这段代码时,jObject 返回:
"test": [
"loginId": "testuser1",
"userCase": "verify for user"
,
"loginId": "testuser2",
"userCase": "verify for user"
]
我的问题是我只想在 JObject 中返回以下数组:
"loginId":"testuser1","userCase":"verify for user"
我研究了一段时间,如果不向新的 JObject 添加密钥,则无法找到解决方案,在这种情况下,密钥是“测试”。
这在 C# 中是否可行?
我也尝试将 JArray 直接添加到 JObject:
JObject jObject = new JObject(new JObject(jsonArray));
但出现错误:System.ArgumentException: '无法将 Newtonsoft.Json.Linq.JArray 添加到 Newtonsoft.json.Linq.JObject
我也尝试过像这样将数组添加到 JObject:
for (int i = 0; i < jsonArray.Count; i++)
jObject[i] = jsonArray[i];
但出现错误:System.ArgumentException:使用无效键值设置 JObject 值:0。应为对象属性名称。
fwiw 这就是我这样做的方式,它是 Java,它就像一个魅力,但我无法在 C# 中弄清楚。 Java 代码:
JSONObject[] jsonObject = new JSONObject[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++)
jsonObject[i] = jsonArray.getJSONObject(i);
【问题讨论】:
JArray.FromObject(myObject);"loginId":"testuser1","userCase":"verify for user"
不是数组而是对象。你能澄清一下你到底想返回什么 - json数组的第一个元素吗?还是将所有元素作为单独的JObject
s?或者只是一个JArray
?
嗨@GuruStron,感谢您的回复。我想将所有元素的 JObject 作为单独的对象返回,如下所示: ["loginId":"testuser1","userCase":"verify for user","loginId":"testuser2","userCase":"验证用户"]
那不是json对象,是json数组,所以需要将返回类型改为JArray
,返回jsonArray
你是对的@GuruStron。我意识到我现在没有问正确的问题。我想返回数组第一个元素的 JObject,像这样:"loginId":"testuser1","userCase":"verify for user",你知道我会怎么做吗?
【参考方案1】:
要获取数组的第一个元素,您可以执行以下操作:
var json = @"
""test"": [
""loginId"": ""testuser1"",
""userCase"": ""verify for user""
,
""loginId"": ""testuser2"",
""userCase"": ""verify for user""
]
";
var testMethodName = "test";
var jObject = JObject.Parse(json);
var first = (JObject)jObject[testMethodName][0]; // note that this can throw for multiple reasons
你的 java 代码的模拟是:
// parse jObject as earlier
var jArr = (JArray)jObject[testMethodName];
var jsonObjectArr = new JObject[jArr.Count];
for (int i = 0; i < jArr.Count; i++)
jsonObjectArr[i] = (JObject)jArr[i];
或者你可以使用LINQ to JSON:
// parse jObject as earlier
var jsonObjectArr = jObject[testMethodName]
.Children<JObject>()
.ToArray();
【讨论】:
【参考方案2】:为什么不像这样只返回数组的第一个对象:
public static JToken FetchOneDatum(string testMethodName)
string jsonString = GetFileContent("sampleTest.txt");
JObject obj = JObject.Parse(jsonString);
JArray jsonArray = JArray.Parse(obj[testMethodName].ToString());
return jsonArray[0];
您可以在此处找到整个 Visual Studio 解决方案: solution on GitHub
【讨论】:
【参考方案3】:C# 方法 ;)
public class Test
public string loginId get; set;
public string userCase get; set;
public class Scenario
public Test[] tests get; set;
// Usage
public static Test FetchData(string testMethodName)
using (var reader = new StreamReader("PathToJsonfile"))
var json = reader.ReadToEnd();
var scenario = JsonConvert.DeserializeObject<Scenario>(json);
return scenario.tests.First();
【讨论】:
以上是关于android 从jobject、jclass获取类名(API>19)(一)的主要内容,如果未能解决你的问题,请参考以下文章
Android jni/ndk编程三:native访问java
从 JSON 检索项目时获取“无法将 Newtonsoft.Json.Linq.JObject 转换为 Newtonsoft.Json.Linq.JToken”