Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/android.js
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,14 @@ export function getArtClassSpec (vm) {
}
}
if (offsetCopiedMethods === -1) {
throw new Error('Unable to find copied methods in java/lang/Thread; please file a bug');
/*
* Android 16 ART no longer exposes a nearby field whose raw value
* matches the methods_ array length for java/lang/Thread. The class
* model derives the actual method count from the methods_ array header,
* so keep a stable placeholder offset here instead of aborting bridge
* initialization on newer ART builds.
*/
offsetCopiedMethods = offsetMethods;
}

spec = {
Expand Down
25 changes: 19 additions & 6 deletions lib/class-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,12 @@ model_new (jclass class_handle,
guint field_array_cursor;
gboolean merged_fields = art_api.class_offset_sfields == 0;

elements = read_art_array (class_object, art_api.class_offset_methods, sizeof (gsize), NULL);
n = *(guint16 *) (class_object + art_api.class_offset_copied_methods_offset);
/*
* On newer ART builds, copied_methods_offset_ is no longer a reliable
* proxy for the total number of ArtMethod entries. The methods_ array
* header already carries the authoritative length, so use that directly.
*/
elements = read_art_array (class_object, art_api.class_offset_methods, sizeof (gsize), &n);
for (i = 0; i != n; i++)
{
jmethodID id;
Expand All @@ -333,7 +337,12 @@ model_new (jclass class_handle,
method = to_reflected_method (env, class_handle, id, is_static);
name = call_object_method (env, method, java_api.method.get_name);
name_str = get_string_utf_chars (env, name, NULL);
modifiers = access_flags & 0xffff;
/*
* ART access_flags are no longer a safe source of Java-level modifiers
* on Android 16. Query the reflected Method object instead so static
* methods like Thread.currentThread() keep their correct dispatch kind.
*/
modifiers = call_int_method (env, method, java_api.method.get_modifiers);

model_add_method (model, name_str, id, modifiers);

Expand Down Expand Up @@ -369,7 +378,11 @@ model_new (jclass class_handle,
field = to_reflected_field (env, class_handle, id, is_static);
name = call_object_method (env, field, java_api.field.get_name);
name_str = get_string_utf_chars (env, name, NULL);
modifiers = access_flags & 0xffff;
/*
* Keep field modifiers aligned with the reflected Java view for the
* same reason as methods: raw ART flags are no longer sufficient.
*/
modifiers = call_int_method (env, field, java_api.field.get_modifiers);

model_add_field (model, name_str, id, modifiers);

Expand Down Expand Up @@ -613,8 +626,8 @@ collect_matching_class_methods (ArtClassVisitor * self,
class_name_length = strlen (class_name);
seen_method_names = ctx->include_signature ? NULL : g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

elements = read_art_array (klass, art_api.class_offset_methods, sizeof (gsize), NULL);
n = *(guint16 *) ((gpointer) klass + art_api.class_offset_copied_methods_offset);
/* Keep enumeration aligned with the authoritative methods_ array length. */
elements = read_art_array (klass, art_api.class_offset_methods, sizeof (gsize), &n);
for (i = 0; i != n; i++)
{
ArtMethod * method;
Expand Down