MonoTouch mysteriously not aot-compiling methods and properties? - c#

I have a strange problem where MonoTouch seems to be either not compiling methods or not able to find a compiled method it is instructed to call, and only on the device in the Release configuration - Debug builds are fine. I've tried reproducing it with a simpler code sample with no luck, so I doubt you will be able to see the behavior with the code below. But this is essentially what I'm doing:
using System;
using MonoTouch.UIKit;
public class MyClass
{
private UINavigationController _navController;
private UIViewControler _viewController;
public UINavigationController NavController
{
get
{
if (_navController == null)
{
if (_viewController == null)
{
_viewController = new UIViewController();
}
_navController = new UINavigationController(_viewController);
}
return _navController;
}
}
}
Then, in some other method...
public void SomeMethod()
{
MyClass myClass = new MyClass();
var navController = myClass.NavController; // <-- This is where it throws
}
The exception I get is the standard JIT compile message, saying that it attempted to JIT get_NavController(). I find this very strange, because there's no virtual generics, no LINQ, the linker is off, and nothing else that normally causes JITs seems to be involved. I've also verified that it will throw for other methods and properties defined on MyClass, but not the constructor or System.Object inherited methods. Reflection reveals that myClass.GetType().GetMembers() has a MemberInfo for everything I would expect. Yet, only for Release|iPhone, I can't access these methods or properties. The only logical conclusion I can come to is that the aot compilation step is missing them, and I don't know why that would happen at all, let alone only in the Release configuration.
My question is, what could be causing such a situation, and what is the next step to fixing it? I'm not even sure where to go from here on debugging this, or what to file a bug about, because I can't reproduce it out of the context of our (much) larger project.
Update: The exact exception text was requested.
System.ExecutionException: Attempting to JIT compile method
'MyNamespace.MyClass.get_NavController ()' while running with --aot-only

This doesn't look like something that can be solved here.
I suggest filing a bug, and attach the entire project if you're unable to make a smaller test case. You can file private bugs only Xamarin employees have access to if you don't want your project to be publicly visible.

Could you try to explicitly declare the variable
UINavigationController navController = myClass.NavController;
Alternatively, I wonder if this is at all associated with needing to wait for the UIViewController.ViewDidLoad method to be called as the internals of the class may not yet have been initialized?
Just shots in the dark here, I can't think of a reason why your code wouldn't work.

Related

What's the explanation of this behavior in C#

Consider this simple console application:
class Program
{
static void Main(string[] args)
{
var human = CreateHuman(args[0]);
Console.WriteLine("Created Human");
Console.ReadLine();
}
public static object CreateHuman(string association)
{
object human = null;
if (association == "is-a")
{
human = new IsAHuman();
}
else
{
human = new HasAHuman();
}
return human;
}
}
public class IsAHuman : Human
{
}
public class HasAHuman
{
public Human Human { get; set; }
}
The Human class is in another assembly, say HumanAssembly.dll. If HumanAssembly.dll exists in the bin directory of our console app, everything would be fine. And as we might expect, by removing it we encounter FileNotFoundException.
I don't understand this part though. Comment human = new IsAHuman(); line, recompile and remove HumanAssembly.dll. Console app won't throw any exception in this case.
My guess is that CLR compiler differentiates between is a and has a associations. In other words, CLR tries to find out and understand and probably load all the types existing in the class definition statement, but it can instantiate a class without knowing what's inside it. But I'm not sure about my interpretation.
I fail to find a good explanation. What is the explanation for this behavior?
You are seeing the behavior of the JIT compiler. Just In Time. A method doesn't get compiled until the last possible moment, just before it is called. Since you removed the need to actually construct a Human object, there is no code path left that forces the jitter to load the assembly. So your program won't crash.
The last remaining reference to Human is the HashAHuman.Human property. You don't use it.
Predicting when the jitter is going to need to load an assembly is not that straight-forward in practice. It gets pretty difficult to reason through when you run the Release build of your code. That normally enables the optimizer that's built into the jitter, one of its core optimization strategies is to inline a method. To do that, it needs access to the method before it is called. You'd need an extra level of indirection, an extra method that has the [MethodImpl(MethodImplOptions.NoInlining)] attribute to stop it from having a peek. That gets to be a bit off into the deep end, always consider a plug-in architecture first, something like MEF.
Here is great explanation of what you are looking for.
The CLR Loader
Specially in the following lines -
This policy of loading types (and assemblies and modules) on demand means that parts of a program that are not used are never brought into
memory. It also means that a running application will often see new
assemblies and modules loaded over time as the types contained in
those files are needed during execution. If this is not the behavior
you want, you have two options. One is to simply declare hidden static
fields of the types you want to guarantee are loaded when your type is
loaded. The other is to interact with the loader explicitly.
As the Bold line says, if you code does not execute a specific line then the types won't be loaded, even if the code is not commented out.
Here is also a similar answer that you might also be interested in -
How are DLLs loaded by the CLR?

NullReferenceException when accessing some object

I know this is a noob error but I really can't discover why it's coming up as I am accessing an object that is set.
The xloc and yloc both being local variables.
gameBorder.FormInstance.tableLayoutPanel1.GetControlFromPosition(xloc, yloc).BackgroundImage = Properties.Resources.Image;
However this has been set within the form class:
namespace csharp_build
{
public partial class gameBorder : Form
{
public static gameBorder FormInstance;
public gameBorder()
{
FormInstance = this;
InitializeComponent();
}
}
}
Any idea why this happens? Would it be to do with the fact that the form class is referenced as gameBorder, and that is what the constructor is called, and the name for the form class in the solution explorer is Form1.cs?
I know this is a noob problem and I do apolagize but any help would be greatly appreciated.
If you are sure that tableLayoutPanel1 exists and is not null, then change your code to this and see what happens:
var control = gameBorder.FormInstance.tableLayoutPanel1.GetControlFromPosition
(xloc, yloc);
if (control == null) throw new NullReferenceException(
"No control at those coordinates");
control.BackgroundImage = Properties.Resources.Image;
jeez, guys, this is code for analysis, debugging, to help figure out illustrate the cause of the issue, that's all.....
WARNING WARNING WARNING: NOT INTENDED AS FINAL PRODUCTION CODE
Thanks to #SriramSakthivel comments below, please Note that NullReferenceException is being thrown here only for debugging/Analysis purposes, and should never be thrown by application code in production release.
The way you chain members and method results makes it hard to determine at a glance what causes the NullReferenceException to be thrown. FormInstance could be null if it's accessed before any gameBorder instances ever get created. Although unlikely, tableLayoutPanel could be null as well. The result of GetControlFromPosition method could very well be too, if no control is on the specified cell.
When you are encountering this kind of problem within this kind of code, the best thing to do is to decompose the calling chain. This way you will be able to quickly tell where the problem lies.
You can also make code assertions, like this:
var formInstance = gameBorder.FormInstance;
Debug.Assert(formInstance != null);
var controlAtPos = formInstance.tableLayoutPanel1.GetControlFromPosition(xloc, yloc);
Debug.Assert(controlAtPos != null);
controlAtPos.BackgroundImage = Properties.Resources.Image; // You may want to make some assertions on resolving your image instance too
The beauty of code assertions is that it's easy to exclude these from compiling into production code. By default, it's compiled in debug configuration and excluded in release configuration. This way you can benefit from the help it provides on debugging without worrying about the extra overhead in deployed code.
Keep this in mind, it will be useful if you ever face this issue again in the future.

Visual studio detecting unused return

I've just spent the best part of an hour trying to work out why some code appered to not be working. I was getting no compilation errors of any sort, and have tracked the bug down to calling a function and doing nothing with the return value. The code was a little more involved than the sample below as Class1 is immutable, but it still demonstrates the issue:
public class Class1
{
private int MyVal = 0;
public int GetMyVal()
{
return MyVal;
}
}
public void Tester(){
Class1 Instance = new Class1();
Instance.GetMyVal();
}
The function call to GetMyVal() is as technically useless as it is technically correct. As I say the code was more involved, but this is the core issue.
I'm slightly surprised that VS 2013 (For Web) fails to highlight the issue as clearly nothing is gained from calling GetMyVal. Is there some switches I'm missing to detect this sort of thing or is this beyond the scope of what Visual Studio can accomplish?
I doubt there is/are (m)any editors out there can can give you what you want.
VS will tell you if you have a variable you're not referencing (at least for Pro and Ultimate. Haven't used Web for 2012/2013). However within the scope of Class1, private int MyVal is being referenced within your GetMyVal function so it will not be marked as an unreferenced property.
It can often catch useless pieces of code but I don't see how you expect it to say that your previously initialized and referenced variable is not meaningful. It has no way of knowing that the property in Class1 isn't something you want to use/modify later.
Do correct me if I am misunderstanding your question
Side note: If you can figure out a way to make it do what you're after,might I suggest writing a plugin? Bear in mind that existing plugins like Resharper and FXCop add a world of functionality

what would make the "this" clause different?

I have the following code:
CustomerService service;
public CustomerService Service
{
get
{
if (this.service == null)
{
this.service = new CustomerService();
}
return this.service;
}
}
public DataTable GetCustomers()
{
return this.Service.GetCustomers();
}
Now the question is: if I wrote the above method as follow (without "this"), it's giving me an error : instance is not reference to an object.
public DataTable GetCustomers()
{
return Service.GetCustomers(); // this will spell the error "instance is not reference to an object"
}
Does anyone know? also it only happens while running via IIS and not from casini web server (VS 2010).
The presence or absence of this cannot explain the error you are witnessing. In this situation they mean exactly the same thing and will compile to the same IL code. Check the assembly using .NET Reflector to verify this if you wish. The error is occurring at random, probably due to a race condition.
One thing I can immediately see is that if you are running this code from multiple threads then it looks like you have a race condition here:
if (this.service == null)
{
this.service = new CustomerService();
}
return this.service;
In the multithreaded case you would need to lock otherwise you could get two CustomerService objects. I'm not sure if this explains your error, but it certainly could create confusion. Race conditions can occur in one environment but not in another as the frequency of the error can depend on the type of the hardware and on what other processes are running on the server.
You may also have other race conditions in the code you haven't posted. Don't use this lazy initialization technique without locking unless you are sure that you have only one thread.
You probably have a name conflict with another 'Service' (class or namespace). The use of this solves it.
I'm a bit skeptical about the difference between Cassinin and IIS, have you carefully checked that?
Something like this should be in a singleton. Which would resolve many issues like threading if implemented correctly and would make the implementation and readability of the code much better.
Thanks
-Blake Niemyjski (.netTiers team member)
I fiddled a bit with your code in Visual Studio and I couldn’t even get a name conflict to produce the error message you described. I can’t think of any case in which “this.X” can ever be different from “X” except when “X” is a local variable or a method parameter.
Would the CustomerService class derive from a base class called Service? If so, then that's the problem.

C# Extension Method Oddity during Unit Test

Using Visual Studio 2008 / C# / VS Unit Testing.
I have a very straightforward extension method, that will tell me if an object is of a specific type:
public static bool IsTypeOf<T, O>(this T item, O other)
{
if (!(item.GetType() is O))
return false;
else
return true;
}
It would be called like:
Hashtable myHash = new Hashtable();
bool out = myHash.IsTypeOf(typeof(Hashtable));
The method works just fine when I run the code in debug mode or if I debug my unit tests. However, the minute I just run all the unit tests in context, I mysteriously get a MissingMethodException for this method. Strangely, another extension method in the same class has no problems.
I am leaning towards the problem being something other than the extension method itself. I have tried deleting temporary files, closing/reopening/clean/rebuilding the solution, etc. So far nothing has worked.
Has anyone encountered this anywhere?
Edit: This is a simplified example of the code. Basically, it is the smallest reproducible example that I was able to create without the baggage of the surrounding code. This individual method also throws the MissingMethodException in isolation when put into a unit test, like above. The code in question does not complete the task at hand, like Jon has mentioned, it is more the source of the exception that I am currently concerned with.
Solution: I tried many different things, agreeing with Marc's line of thinking about it being a reference issue. Removing the references, cleaning/rebuilding, restarting Visual Studio did not work. Ultimately, I ended up searching my hard drive for the compiled DLL and removed it from everywhere that did not make sense. Once removing all instances, except the ones in the TestResults folder, I was able to rebuild and rerun the unit tests successfully.
As to the content of the method, it was in unit testing that I discovered the issue and was never able to get the concept working. Since O is a RunTimeType, I do not seem to have much access to it, and had tried to use IsAssignableFrom() to get the function returning correctly. At this time, this function has been removed from my validation methods to be revisited at another time. However, prior to removing this, I was still getting the original issue that started this post with numerous other methods.
Post-solution: The actual method was not as complex as I was making it out to be. Here is the actual working method:
public static void IsTypeOf<T>(this T item, Type type)
{
if (!(type.IsAssignableFrom(item.GetType())))
throw new ArgumentException("Invalid object type");
}
and the unit test to verify it:
[TestMethod]
public void IsTypeOfTest()
{
Hashtable myTable = new Hashtable();
myTable.IsTypeOf(typeof(Hashtable));
try
{
myTable.IsTypeOf(typeof(System.String));
Assert.Fail("Type comparison should fail.");
}
catch (ArgumentException)
{ }
}
Usually, a MissingMethodException means that you are loading a different version of the dll to the one you referenced during build, and the actual dll you are loading (at run-time) doesn't have the method the compiler found (at compile-time).
Check that you haven't somehow got various versions of the dll referenced by different projects. It could be that when you run it in debug mode, some other code makes the correct dll load first, but when running in-context, this other code doesn't run - so the incorrect version loads instead.
This would apply doubly if the failing method was added recently, so might not be in the older version referenced.
If you are using full assembly versioning, you might be able to watch the debug output to see exactly which assembly loads.
I am speculating here.
Put a constraint on the method to see if that helps
Pseudocode
public static bool IsTypeOf(this T item, O other) Where T: object, O: Type
{
}
Also, which class is this method in?
EDIT: Is this class, part of the assembly which is being tested?

Categories