Managed Code Managed code is a term describing code running in a managed environment whether on a server, personal computer, mobile device, or in an embedded system. A runtime engine oversees resource allocation, threading, and synchronization needs, and enforces the type safety of executing code, preventing illegal memory access. It is a level of abstraction above native code that greatly increases developer productivity and the reliability of the code produced. The lifetime of objects and other types allocated by running code is tracked by the runtime engine, freeing the developer of the burden of this task. When managed code is compiled, it generates binary instructions that also include rich meta-data descriptions of the classes, types, variables, and any other information necessary to manage the code's execution. This meta data describing the code is what allows a managed-code runtime to perform its administration and supervision services. Rich meta data is a key difference between native code and managed code. Some additional common features of many managed code environments include the following:Processor independence Managed code is not compiled into processor-specific instructions but is instead compiled into an intermediate language. Intermediate language is often shortened to IL and also referred to as "byte codes" in some runtime environments; all these terms mean the same thing. This IL is then converted on the device to the appropriate executable format. Compiling into an IL format can allow the same compiled code to run on not just different processors but also different address sizes; for example, the same IL component can run on 32- or 64-bit processors because the instructions are not processor-address-size specific.Operating system independence Managed-code runtimes and their programming libraries enable developers to program targeting an abstraction on top of the core operating system. Although "write once, run anywhere" is not a practical goal given the significant differences in user interface and user interaction models on different classes of devices having a degree of abstraction above, the operating system is still very useful for porting applications to target different device classes. In addition, the ability to build headless (headless = no user interface) components that can be run on different devices without recompilation is very useful for building reusable modules. Common code can be placed into headless components leaving only the need to implement device-specific user interfaces that use those common modules.JIT (just-in-time compilation) and/or interpretation of code There are two methods for executing managed code: (1) JITing, where the IL is translated into native processor instructions and then executed; or (2) interpretation, where each IL instruction is looked at and predefined libraries are called to execute the intent of the IL. JITing produces the fastest-executing code, but interpreters are easier to build because they do not need to know how to generate processor-specific instructions. Often an interpreter is first built to quickly port a managed runtime to a new processor and then JIT compilers are built to optimize for specific popular processors. The same IL can either be interpreted or JITed; the choice is up to the implementer of the runtime.Garbage collection Garbage collection is the way managed-code environments remove the burden of low-level memory management from application developers. There are many different strategies for garbage collection, each optimized for different scenarios. It is an ongoing research subject to discover ever-more-optimal strategies for important scenarios. A common strategy employed on device runtimes is "mark and sweep," where periodically the runtime will start with the list of all variables currently in scope and trace all of the objects referenced by these objects. Each object that is found this way is "marked" to indicate it is still being used. In this way a live-object tree is built representing the full set of all objects that can be reached by the application's code. When all live objects are marked, a sweep is performed to release all objects not reachable by the application. Garbage collectors can be highly complex systems, and many optimizations are possible to maximize performance on servers, desktops, and devices. Organizations building managed-code runtimes spend a great deal of time tuning their garbage collection strategy for maximum performance and reliability.Versioning One of the things meta data can be used for is to supply rich information about the version of a component and the versions of other components that it is dependent on. Managed runtimes with this capability can manage multiple versions of the same components on the same machine, allowing each component to bind to the specific component it was built and tested against. This is important for the long-term stability of machines running multiple applications. Built-in versioning support avoids versioning conflicts and both the subtle and overt kinds of problems improper versioning can bring about.Security support Managed code can also enforce security policy on the device. Managed-code runtimes that have rich security support can set policy for which services any specific piece of code will be granted. This is often referred to as "evidence-based security." Typical examples of security policy include "Code signed by a trusted third party can run with full capabilities," "Code present on the local file system will have access to files in a specific set of folders," "Code downloaded from the Internet that is not signed by a trusted party will run with minimal permissions and generic file i/o is not allowed." Different runtimes have different levels of support for security; for example, J2ME and .NET Compact Framework v1.1 have different support for security. The .NET Compact Framework supports a subset of the desktop and server .NET Framework security policy. Two of the most common managed-code environments for mobile devices are J2ME (Java Mobile Edition) and the .NET Compact Framework. This book shows the principals of software engineering for mobile devices using the .NET Compact Framework, although most of the principals discussed are valid for all kinds of mobile device development, including native code.The benefits of managed code cannot be overstated. As a general rule, if it is possible to use managed code for a software development project, use it. Your code will get developed faster, will run with fewer bugs, will be easier to port to new devices, will run safer and with higher stability, and will be more maintainable than the native code implementation would be. Native code development should be used only when absolutely required for performance reasons or for low-level access. Even in these cases it is best to write the small necessary bit of critical code in native code and build the rest of the application in higher-level managed code. As you will see later in this book, with good mobile device software engineering practices as well as managed runtimes supporting JIT compilation, very few tasks should require native code. Even many action-oriented highly animated games are possible in managed code. The benefits the higher-level abstractions of managed code bring are overwhelmingly compelling. Ten to twenty years ago people moved from developing applications in assembly code to writing them in C, reserving assembly code for only the most focused and critical tasks. This increased level of abstraction allowed far more complex applications to be developed more quickly and with greater reliability. The same kind of transition is now underway from native C/C++ to managed-code environments.The .NET Compact FrameworkA Managed-Code Runtime for Devices This book uses the .NET Compact Framework to demonstrate good mobile software engineering practices, so it is worth giving a high-level overview of the .NET Compact Framework in this introductory chapter. A later chapter is devoted to describing in more detail how the .NET Compact Framework works and how it manages memory, compiles code, and collects garbage. Developers choosing other mobile device programming models will find many of the concepts similar.The .NET Compact Framework is composed of two major pieces:a core native code engine, anda larger set of managed class libraries.The Core Execution Engine The .NET Compact Framework core engine is written in native code. Its job is to load managed code, compile it, run it, and perform all the tasks involved in managed-code execution. The .NET Compact Framework has been ported to several different processor families including x86, StrongARM, SH3, MIPS, and others.
Floating Point: What's in a Number? The .NET Compact Framework's execution engine and runtime libraries have built-in support for floating-point mathematics. This is specifically worth pointing out because not all mobile device runtimes do. If you are coming from the perspective of desktop or server development, this is important to understand.For example, the Java J2ME CLDC (Common Limited Device Configuration) version 1.0 does not require floating-point support, but the J2ME CLDC v1.1 does. Java's MIDP 2.0 only (Mobile Information Device Profile) requires only CLDC 1.0 support. If you are targeting a mobile device with a J2ME runtime, make sure you know which version it supports.Most rich mobile applications require some form of decimal arithmetic. Although it is possible to simulate some floating-point operations with fixed-point integer mathematics, this can be cumbersome and is limited in its flexibility to handle advanced needs.When you are defining your mobile application's runtime requirements, pay careful attention to the math support present in the runtime, not only for floating point but also currency and date/time. Advanced math libraries for subjects such as trigonometry and exponent support are also useful things to verify. The .NET Compact Framework has built-in support for all of these.The benefit of a runtime not supporting floating-point math is the ability to fit into smaller spaces and run in simpler environments. The big drawback is limited functionality for application developers. Take a careful look at your needs and choose a runtime and target device that offers you the right degree of functionality and flexibility. |
The Class Libraries These are the programming APIs that developers use to build their applications. They can logically be broken into four pieces:Base class libraries These are the nuts and bolts of programming. Support for strings, arrays, collections, file i/o, threading, networking, and pretty much all of the things you expect to be available when writing code are in the base class libraries.Drawing/forms The drawing and forms libraries contain support for 2D drawing, as well as support for rich forms and controls with which to build user interfaces.Data access The data access libraries offer an in-memory relational-tables model called ADO.NET for working with data created in memory, loaded from XML, or queried from a database.XML and Web services These libraries contain support for working with XML as well as making Web service calls to pass information between devices and servers via XML and SOAP.Portability The .NET Compact Framework execution engine and class libraries were designed in such a way as to enable the relatively straightforward porting of them to multiple device types and different operating systems. The first devices that have been targeted are Windows CE 4.1, the Pocket PC 2000/ 2002/2003/and beyond, and the Microsoft Smartphone operating system. Other non-Microsoft platforms may be supported in the future.It is also worth pointing out that because the .NET Compact Framework was built on top of the CLI (Common Language Infrastructure) ECMA and ISO standards, it is quite possible for another organization to build its own device-targeted CLI implementation for C# and VB.NET development. Such an implementation would be likely to have the same base class libraries but potentially different higher-level libraries. There are already at least two independent third-party CLI implementations for desktops and servers. |