D/Retrofit﹕java.lang.SecurityException: Can't make field constructor accessible
at java.lang.reflect.Constructor.setAccessible(Constructor.java:334)
at com.google.gson.internal.ConstructorConstructor.newDefaultConstructor(ConstructorConstructor.java:97)
at com.google.gson.internal.ConstructorConstructor.get(ConstructorConstructor.java:79)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:82)
at com.google.gson.Gson.getAdapter(Gson.java:359)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:52)
at com.google.gson.Gson.getAdapter(Gson.java:359)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getFieldAdapter(ReflectiveTypeAdapterFactory.java:122)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.access$100(ReflectiveTypeAdapterFactory.java:46)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:92)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:91)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:142)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:83)
at com.google.gson.Gson.getAdapter(Gson.java:359)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getFieldAdapter(ReflectiveTypeAdapterFactory.java:122)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.access$100(ReflectiveTypeAdapterFactory.java:46)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:92)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:91)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:142)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:83)
at com.google.gson.Gson.getAdapter(Gson.java:359)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:52)
at com.google.gson.Gson.getAdapter(Gson.java:359)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getFieldAdapter(ReflectiveTypeAdapterFactory.java:122)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.access$100(ReflectiveTypeAdapterFactory.java:46)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:92)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:91)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:142)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:83)
at com.google.gson.Gson.getAdapter(Gson.java:359)
at com.google.gson.Gson.fromJson(Gson.java:809)
at com.google.gson.Gson.fromJson(Gson.java:775)
at retrofit.converter.GsonConverter.fromBody(GsonConverter.java:63)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:367)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)
Originally filed at https://github.com/square/retrofit/issues/870.
Note: this might be a bug in the preview OS runtime and not Gson, but it's definitely not a Retrofit problem.
Maybe relevant: http://developer.android.com/preview/behavior-changes.html#behavior-art-runtime
Not exactly the cause here, but not surprising that since it's in the same vein it might have been effected.
@JakeWharton I tried simulate this error without success.
I used the android emulator with api version 22. Can you provide more information like device and the class that generated the problem?
Are we trying to deserialize an instance of java.lang.reflect.Field ? It's pretty reasonable that that doesn't work. Here's a snippet of Constructor.java:
public void setAccessible(boolean flag) {
Class<?> declaringClass = getDeclaringClass();
if (declaringClass == Class.class) {
throw new SecurityException("Can't make class constructor accessible");
} else if (declaringClass == Field.class) {
throw new SecurityException("Can't make field constructor accessible");
} else if (declaringClass == Method.class) {
throw new SecurityException("Can't make method constructor accessible");
}
super.setAccessible(flag);
Seems a reasonable guess. This isn't my original bug, I was just moving it from a project I work on.
I get this with an app on a Nexus 6 running Android M.
just updated the Nexus 5 to the latest Android M preview and getting the same error. As it was working before, it seems to be only a problem with the most recent version of Android M (Build MPA44I)?
Hopefully Google will fix it before releasing Android M. Gson is used in a fairly large number of Android projects, and breaking them will be a big no no.
@cdreier are you using Gson on an instance of java.lang.reflect.Field? That's superweird.
The right fix for this is to write a type adapter for that class.
@swankjesse no, i'm using Retrofit for a few rest-calls. I think i figured out a bit more, perhaps something changed in the List interface?
Simple Retrofit service:
public interface SynchronisationService {
@GET("/rooms/all")
public void getAll(Callback<List<Room>> rooms);
}
Room is a stupi POJO, but with a List of light-switches...
public class Room {
private String name;
private int id;
private List<LightSwitch> switches;
/** ... **/
}
Response is something like this:
[
{
"name": "livingroom",
"id": "1",
"switches": [
{
"name": "big lamp",
"id": "1"
},
{
"name": "smaller lamp",
"id": "2"
}
]
}
]
Without this switch-list in my room, everything is working fine!
If i want Retrofit / gson to parse my switch-list directly in the room, im getting the stacktrace Jake Wharton posted.
You can try adding GsonConverter
new GsonConverter(new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.serializeNulls()
.create())
In your RestAdapter.Builder()
RestAdapter.Builder()
.setConverter(new GsonConverter(new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.serializeNulls()
.create()))
.setEndpoint(endPoint)
.build()
I am using Retrofit and GSON in a project and only encountered this issue on Android M after replacing SugarORM with ActiveAndroid.
Is there any progress with this one? It is present with the official Android 6 release.
We experienced this same issue on our app on official Android 6 release. Adding this to our GsonBuilder as seen above seemed to resolve the issue.
new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
perhaps something changed with the reflection api in android 6?
my workaround was to declare these fields causing the error as transient.
public class Switch {
public String name;
public Room room;
public int id;
private transient SwitchService switchService;
}
yeah @crowdcast-hk already resolve this issue. its work.
It seams bug has been fixed in new version (2.4) .
"com.google.code.gson:gson:2.4"
upgraded to 2.4 but app still crashes with the same exception on Marshmallow
Did you try to exclude fields with modifiers?
new GsonBuilder().excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
@inisic if you need to add these lines, problem is not fixed :)
In my case, I don't use gson with retrofit (only gson) but i have the same problem.
If i only add
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
problem is still here. To solve my problem, i have to set
excludeFieldsWithoutExposeAnnotation()
But i have to expose all fields i need ><. Is there a way to know where is the problem ? In the stacktrace, there is no reference to my code
This exclude(excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) didn't help me. Class which extends Object is deserialized correctly, but classes which extends Model from ActiveAndroid throws exception. I found only one solution => write custom deserializer. I hope this is only temporary solution and this will be fix at GSON library.
The cause continues to seem like the use of Class or Field in the
serialized object's fields without marking it transient. There is no reason
to be serializing either of these types.
On Tue, Oct 27, 2015, 9:02 PM DavidKrybus [email protected] wrote:
This exclude(excludeFieldsWithModifiers(Modifier.FINAL,
Modifier.TRANSIENT, Modifier.STATIC) didn't help me. Class which extends
Object is deserialized correctly, but classes which extends Model from
ActiveAndroid throws exception. I found only one solution => write custom
deserializer. I hope this is only temporary solution and this will be fix
at GSON library.—
Reply to this email directly or view it on GitHub
https://github.com/google/gson/issues/648#issuecomment-151687960.
I'm in the same boat. My tests pass running in API 22, but fail for API 23.
I had the same issue. I'm using Gson with Retrofit and ActiveAndroid.
The solution with
excludeFieldsWithoutExposeAnnotation()
suggested by @aat-antoine works for me.
Im using Retrofit + Gson so I used the excludeFIeldsWithouAnnotation() option and it worked.
Retrofit retrofit =
new Retrofit.Builder()
.baseUrl(Api.ENDPOINT)
.addConverterFactory(
GsonConverterFactory.create(new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create()))
.client(new OkHttpClient())
.build();
@jirivrany Thanks excludeFieldsWithoutExposeAnnotation() worked for me.
I'm having this issue on Android M as well. Any idea what Can't make field constructor accessible refers to? I think setting _that_ to transient would be a better solution than using the @Expose property on every single member.
You’re using Gson to encode an instance of java.lang.reflect.Field. Don’t do that.
@swankjesse That's an log error I'm getting (along with everyone else using Gson in this thread) while using the default Gson instance on Android 6.0.
Anyone using ActiveAndroid having problems using the .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) workaround? Any data that is persisted using the default GsonBuilder() and then models deserialized with the new exclude rule causes some errors querying / storing models deserialized against this new rule.
@AeroEchelon I was trying to use ActiveAndroid and Gson and my workaround is fine for parsing the data with gson, but when I try to save fields that have relationships it doesnt work.
I use Gson's ExclusionStrategy to skip java.lang.reflect.Field and java.lang.reflect.Method, my simple demo.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String json = "{\"name\": \"Ricky\", \"age\": 25}";
ExclusionStrategy exclusionStrategy = new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return false;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return clazz == Field.class || clazz == Method.class;
}
};
Gson gson = new GsonBuilder()
.addSerializationExclusionStrategy(exclusionStrategy)
.addDeserializationExclusionStrategy(exclusionStrategy)
.create();
// Student is a simple class extends com.activeandroid.Model
Student student = gson.fromJson(json, Student.class);
student.save();
List<Student> students = new Select().from(Student.class).execute();
if (students != null && students.size() > 0) {
Student stu = students.get(0);
Log.d("zlx", stu.name + "'s age: " + stu.age);
}
}
I had the same problem when using Retrofit + Gson + ActiveAndroid, but when i insert this line excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)" in my GsonBuilder() it worked, but I do not understand what happened :(
:+1: to excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
@jirivrany excludeFieldsWithoutExposeAnnotation()work for me
i tried this like
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
.excludeFieldsWithoutExposeAnnotation()
.create();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient)
.build();
but still getting same error. i am using retrofit + GSON+ Active Android.
what should i do for this...
I'm using OkHttp + Gson + ActiveAndroid
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC);
Gson gson = builder.create();
work for me
This continues to look like the serialization of java.lang.reflect.Field or java.lang.reflect.Method. No action to take.
I'm using Retrofit+ Gson + ActiveAndroid
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC);
Gson gson = builder.create();
worked for me
Mmm. Did you using extension of Kotlin language?
I have same problem when using kotlin extension, details below:
I've writen function exension for base model:
ModelExtension.kt
fun Model.toJson(): String {
return try {
Gson().toJson(this@toJson, Model::class.java)
} catch(exception: Exception) {
"{}"
}
}
I move it into Model class and it solve my problem...
I use Gson's ExclusionStrategy to skip
java.lang.reflect.Fieldandjava.lang.reflect.Method, my simple demo.@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String json = "{\"name\": \"Ricky\", \"age\": 25}"; ExclusionStrategy exclusionStrategy = new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes fieldAttributes) { return false; } @Override public boolean shouldSkipClass(Class<?> clazz) { return clazz == Field.class || clazz == Method.class; } }; Gson gson = new GsonBuilder() .addSerializationExclusionStrategy(exclusionStrategy) .addDeserializationExclusionStrategy(exclusionStrategy) .create(); // Student is a simple class extends com.activeandroid.Model Student student = gson.fromJson(json, Student.class); student.save(); List<Student> students = new Select().from(Student.class).execute(); if (students != null && students.size() > 0) { Student stu = students.get(0); Log.d("zlx", stu.name + "'s age: " + stu.age); } }
This worked for me, thanks @zhenglingxiao
Most helpful comment
@jirivrany
excludeFieldsWithoutExposeAnnotation()work for me