I am trying to find memory leaks in my Android application.
I have the following situation:
class A created a class A$24 which created a thread. This thread has a reference to class A, so this is the leak.
I understand that A$24 is an anonymous class created in class A, but how can i find out where is was created, in which line in the code.
My problem is to understand who is the problematic thread.
In the project explorer of the resource perspective use the view menu, select "Customize view..." and uncheck "Inner class files" and "Java output folders". Now you should see the generated class files in the project explorer in a "bin" folder.
If you navigate to your A$24.class file, you can open it using a double click. Look for lines at the top talking about field selectors, like this
// Field descriptor #10 Z
private final synthetic boolean val$fStartMinimized
In this example, a final field fStartMinimized is used by the anonymous class (and therefore copied into the anonymous class). Using that field name you should be able to locate the anynomous class in question.
If there is no such field declaration (and also no method name giving you a clue), then you may get more insight with the ByteCode outline plugin (but I've never used that myself).
Related
I have Unable to create application im.app.android.core.AppDemoApplication: e3.b: com.pushserver.android.huaweiPushClient cant cast com.myApp.android.push_lib.huawei.HcmPushClient to PushClient error
What proguard rule should I add? I have tried -keep class com.myApp.android.push_lib.** { *; } but after that I just see the blank screen - no crash, just stuck when trying to start.
Not really an answer, but too long for a comment. I'll update this answer in case we make progress.
1. What is the "normal bug"?
can't cast com.myApp.android.push_lib.huawei.HcmPushClient to PushClient
This means that somewhere in your code you are assigning/passing an instance of HcmPushClient to something that is expecting it to be a PushClient. I would assume that PushClient is some class that you defined in your project, but is does not extend from HcmPushClient. Try to find this piece of code and fix it or add it here to your question.
2. What does ProGuard have to do with this?
Actually, I think not much. If ProGuard would create this error, the message would look more like
can't cast com.myApp.android.push_lib.a.b to c
But since all class names in the error message are the original ones, it does not seem like ProGuard is making issues here. BUT: You can still decypher the message a little bit, because this part is obfuscated:
Unable to create application im.app.android.core.AppDemoApplication: e3.b:
e3.b refers to a class that was obfuscated by ProGuard. To find out what class it is, you can check the file /build/outputs/mapping/release/mapping.txt in your project folder. This is a simple text file that stores the information what class name was renamed to what obfuscated name. In this file search for -> e3 to find the class that was renamed to e3. Somewhere close to this line, you should also be able to find out what exactly e3.b is. Could be a method, could also be a member variable or an inner class.
I hope these two points will bring you closer to make the app run.
I have a MonoBehaviour class that has a property referencing another class which is ScriptableObject.
I've created several prefabs of my first class and created several ScriptableObjects of my second class, I've referenced them in the first class respectively.
In the editor everything works fine, except sometimes my so are shown in the Inspector as Missing Script and in property reference as NameOfSO (), don't know what causing this, but again, Play in the Editor is working just fine.
If build my game for Android and connect to the Debug, to see what's going on, I can clearly see, that's ScriptableObject reference is null. Why? Don't know, came here to ask a question.
Thanks!
I figured it out, turns out this was happening because of the weird thing with namings.
Allow me to explain, when I first created a class from ScriptableObject I used, lets say, MyClas name, I've created several instances of that class, but then I saw the error in the name of the class, I've changed it to the MyClass but only in the file itself, not the actual .cs file, so, this was happening. All I had to do is to ensure that my class and my file names are the same, delete old instances of ScriptableObject and create new ones from scratch and... Voila!
Sorry.
I'm building a Xamarin android app.
After xamarin update I get a build error. I can't tell if that is related at all but what worked before now throws an exception: ClassNotFoundException. The class exists and is a proper activity. There was no change in that area at all.
I've seen many SO threads in that regard but they all suggest to clean solution, delete build folder etc. And that doesn't help me unfortunately.
What I realise is that in the exception message
W/monodroid( 4201): JNIEnv.FindClass(Type) caught unexpected exception: Java.Lang.ClassNotFoundException: md56629fa8edd4a41a77563f74c5f9a5f792.MainActivity the md5 part is not the same as the folder where the MainActivity.class resides in (md56b5cfc81a7b5c4227a0c9a4dcb7dab856). When I delete that folder a new one is generated during a build. Its md5 is different again. But the exception reappears, asking for the same old md5 as before.
My questions:
1.) What can I do to make JNIEnv look for the right md5?
2.) How are those md5 generated and why
Thanks.
Xamarin generates an MD5 sum for all types that have a Android Callable Wrapper (ACW), unless you explicitly give it a name. I guess this is done to avoid collisions with other types, which could live in the same package name. These are generated at build time.
In order to set your own name on a type inheriting from Java.Lang.Object, these are types like Activity, Adapter, View and many more. You simply add a Register attribute to your class:
[Register("my.cool.package.MyTypeName")]
public class MyTypeName : SomeJavaType
{
}
For classes such as Activity you can alternatively use the Name property in the Activity attribute:
[Activity(Label = "MyActivity", Name = "my.cool.package.MyActivity")]
public class MyActivity : Activity
{
}
I make sereval Android apps with similar code, but I need to stay flexible for customizing the apps. My solution right now is, that I have a Library-Project, where I can override functionality in the Project by extending classes. For the following example, I call the Library Project PL. P1 is a customized Project using PL and P2 is another customized Project using PL.
My Problem is now, that in PL I would like to make an instance from StudentPL.java. In P1, there is no need to make any changes to StudentPL, so the compiler should take this class, but in P2, there I have StudentP2.java, that extends from StudentPL.java. So the instance made in PL, should be an instance of StudentP2.java.
My idea was now, that I make a package called mirror, that is directly in the src-Folder of the Project PL. There I make the class mirror.Student.java that extends from StudentPL.java. In the Library-Project, I make now an instance of Student.java. For Project P1, there are no changes needed. In P2 I make the same folder mirror in src Folder and I make the same class mirror.Student.java that extends from StudentP2.java now. The Idea is, that the ClassLoader now loads mirror.Student.java from P2 and ignores mirror.Student.java from PL, but this results in the following error:
Dex Loader] Unable to execute dex: Multiple dex files define Lmirror/Student;
Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lmirror/Student
Here is a UML of what I'm talking about:
http://www.koenix-band.ch/images/other/Stackoverflow.gif
Maybe I should overwrite the ClassLoader, but I have no idea how to do this? Does anyone have an idea to solve this problem? Maybe someone has another idea, how i could customize the apps.
Michael
In my opinion it would be better to make your MainActivityPL abstract with a setStudent or similar method. The bulk of the activity and all its logic would still be shared from your library, but it would allow your other projects an option to use different student objects by extending the StudentPL class.
General question:
Is it possible to use a ClassLoader to replace a pre-loaded (by the system, e.g. found in Android's %android%/frameworks/base/preloaded-classes file) class?
Specific:
I am attempting to use the DexClassLoader to replace a class found in android.net.* before creating a WebView in my application. I can get a Class object, but getMethods() for example gives me an array I'd expect in the unmodified/original class implementation. Is this due to the preloaded-classes system?
Basic setup & pseudo code:
Modify android.net.* class, adding a few test methods/etc.
Compile and end up with classes.dex
jar cf mytest.jar classes.dex
Include mytest.jar in APK assets
Create DexClassLoader and get Class via loadClass()
getMethods() on Class object returns an array I'd expect to see without modifications present in #1
I can provide more details on the setup I'm using and code if needed.
No you can not. WebView is part of the boot class path, and thus the base class loader. There is nothing you can do to make it use classes in another class loader. In fact, it has already been loaded and linked to the classes it uses before your app is even launched (as part of the zygote process pre-initialization).