1 / 54

Chapter 5 Exceptions and Object Lifetime. Prepared By: Mrs.Swetha G & Mrs. Suganthi

Chapter 5 Exceptions and Object Lifetime. Prepared By: Mrs.Swetha G & Mrs. Suganthi Department: ISE & CSE Date : 07 / 10 / 2014. Topics Covered: Ode to Errors, Bugs and Exceptions System. Exception Class The Basics of Object Lifetime The CIL of new

maudie
Download Presentation

Chapter 5 Exceptions and Object Lifetime. Prepared By: Mrs.Swetha G & Mrs. Suganthi

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 5 Exceptions and Object Lifetime. Prepared By: Mrs.Swetha G & Mrs. Suganthi Department: ISE & CSE Date : 07 / 10 / 2014

  2. Topics Covered: • Ode to Errors, Bugs and Exceptions • System. Exception Class • The Basics of Object Lifetime • The CIL of new • Finalizing a Type and Finalization process. • Handling Multiple Exceptions. • The System.GC Type • Important Questions

  3. Bugs: • This is an error on the part of the programmer. • For example, in C++. If you make calls on a NULL pointer or fail to delete allocated memory (resulting in amemory leak), you have a bug. • User errors: • Are caused by the individual running your application, rather than by those who created it. • For example, an end user who enters string into a text box could very well generate an error if you fail to handle this faulty input in your code base.

  4. Exceptions: • Are runtime anomalies that are difficult, if not impossible, to account for while programming the application. • Possible exceptions include attempting to connect to a database that no longer exists, opening a corrupted file, or contacting a machine that is currently offline. • In each of these cases, the programmer (and end user) has little control over these “exceptional” circumstances.

  5. The Atoms of .NET Exception Handling • Programming with structured exception handling involves the use of four interrelated entities: • A class type that represents the details of the exception that occurred • A member that throws an instance of the exception class to the caller • A block of code on the caller’ s side that invokes the exception-prone member • A block of code on the caller’s side that will process (or catch) the exception should it occur

  6. The System.Exception Base Class • All user and system defined exceptions are derived from the System.Exception base class. • This is in turn derived from System.Object Class. • One can use 4 keywords to handle exception: • Try • Catch • Throw • Finally

  7. The System.Exception Base Class public class Exception : ISerializable, _Exception { public virtual IDictionary Data { get; } protected Exception(SerializationInfo info, StreamingContext context); public Exception(string message, Exception innerException); public Exception(string message); public Exception(); public virtual Exception GetBaseException(); public virtual void GetObjectData(SerializationInfo info, StreamingContext context); Contd…..

  8. public System.TypeGetType(); protected intHResult { get; set; } public virtual string HelpLink { get; set; } public System.ExceptionInnerException { get; } public virtual string Message { get; } public virtual string Source { get; set; } public virtual string StackTrace { get; } public MethodBaseTargetSite { get; } public override string ToString(); }

  9. Consider a simple Car.cs public class Car { private intcurrSp; private string petName; public Car(){} public Car(string name, int speed) { petName = name; currSp = speed; } public override string ToString() { return string.Format("{0} is going {1} MPH“,petName, currSp); } }

  10. Any number of objects can be allocate using the C# new keyword. • The “new” keyword returns a reference to the object on the heap, not the actual object itself. • This reference variable is stored on the stack for further use in your application.

  11. To invoke members on the object, apply the C# dot operator to the stored reference:  class Program { static void Main(string[] args) { Car refToMyCar = new Car("Zippy", 50); //We are returned a reference to this object. Console.WriteLine(refToMyCar.ToString()); Console.ReadLine(); } }

  12. The Basics of Object Lifetime • Once “new-ed,” Allocate an object onto the managed heap. • The garbage collector will destroy the object when it is no longer needed. • To determine when an object is no longer needed? The garbage collector removes an object from the heap when it is unreachable by any part of your code base.

  13. Example : public static void MakeACar() { // If myCar is the only reference to the Car object, it may be destroyed when the method returns. Car myCar = new Car(); ... }

  14. The CIL of new When comliler encounters “new”, it will emit a CIL new obj instruction into the method implementation. Example of CIL statements within the MakeACar()method: .method public hidebysig static void MakeACar() cil managed { // Code size 7 (0x7) .maxstack 1 .locals init ([0] class SimpleFinalize.Car c) IL_0000: newobj instance void SimpleFinalize.Car::.ctor() IL_0005: stloc.0 IL_0006: ret } // end of method Program::MakeACar

  15. The managed heap maintains a pointer (next object pointer or new object pointer) that identifies exactly where the next object will be located. • the new obj instruction informs the CLR to perform the following core tasks: • Calculate the total amount of memory required for the object to be allocated • Examine the managed heap to ensure that there is indeed enough room to host the object to be allocated • Finally, before returning the reference to the caller, advance the next object pointer to point to the next available slot on the managed heap.

  16. Rule: If the managed heap does not have sufficient memory to allocate a requested object, a garbage collection will occur. When a collection does take place, the garbage collector temporarily suspends all active threads within the current process to ensure that the application does not access the heap during the collection process. Once the garbage collection cycle has completed, the suspended threads are permitted to carry on their work.

  17. The Role of Application Roots A root is a storage location containing a reference to an object on the heap. A Root can fall into any of the following categories: • References to global objects • References to currently used static objects/static fields • References to local objects within a given method • References to object parameters passed into a method • References to objects waiting to be finalized • Any CPU register that references a local object

  18. During a garbage collection process, • The runtime will investigate objects on the managed heap to determine if they are still reachable (aka rooted) by the application. • To do so, the CLR will build an object graph, which represents each reachable object on the heap.

  19. Object graphs are constructed to determine which objects are reachable by application roots

  20. Example : • Managed heap contains a set of objects named A, B, C, D, E, F, and G. • Objects are examined for active roots. • Once the graph has been constructed, unreachable objects are marked as garbage. • Once an object has been marked for termination, they are swept from memory. • The remaining space on the heap is compacted, which in turn will cause the CLR to modify the set of active application roots to refer to the correct memory . • Last but not least, the next object pointer is readjusted to point to the next available slot.

  21. The garbage collector makes use of two distinct heaps. 1.Used to store very large objects. This heap is less frequently consulted during the collection cycle, given possible performance penalties involved with relocating large objects. 2. Used to store normal objects. Regardless of this fact, it is safe to consider the “managed heap” as a single region of memory. A clean and compacted heap. illustrates the resulting readjustment.

  22. Understanding Object Generations • When the CLR is attempting to locate unreachable objects, is does not examine each and every object placed on the managed heap. • Each object on the heap is assigned to a specific “generation.” • Generation 0: Identifies a newly allocated object that has never been marked for collection • Generation 1: Identifies an object that has survived a garbage collection • Generation 2: Identifies an object that has survived more than one sweep of the garbage collector

  23. The garbage collector will investigate all generation 0 objects first. If marking and sweeping these objects results in the required amount of free memory, any surviving objects are promoted to generation 1. If all generation 0 objects have been evaluated, but additional memory is still required, generation 1 objects are then investigated for their “reachability” and collected accordingly. Surviving generation 1 objects are then promoted to generation 2.

  24. The System.GC Type System.GC allows you to programmatically interact with the garbage collector using a set of static members. Make use of the members of System.GC, when creating types that makes use of unmanaged resources.

  25. System.GC Members • WaitForPendingFinalizers() : Suspends the current thread until all finalizable objects have been finalized. This method is typically called directly after invoking GC.Collect(). • SuppressFinalize() Sets a flag indicating that the specified object should not have its Finalize()method called. • GetTotalMemory() Returns the estimated amount of memory (in bytes) currently allocated on the managed heap. The Boolean parameter specifies whether the call should wait for garbage collection to occur before returning.

  26. MaxGeneration () returns the maximum of generations supported on the target system. Under Microsoft’s .NET 2.0, there are three possible generations (0, 1, 2). • CollectionCount() Returns a numerical value representing how many times a given generation has been swept. • Collect() Forces the GC to perform a garbage collection. • RemoveMemoryPressure() object’s “urgency level” regarding the garbage collection process. Be aware that these methods should alter pressure in tandem and thus never remove more pressure than the total amount you have added.

  27. AddMemoryPressure(), Allow you to specify a numerical value that represents the calling • Collect() Forces the GC to perform a garbage collection. • CollectionCount()  Returns a numerical value representing how many times a given generation has been swept • GetGeneration() Returns the generation to which an object currently belongs.

  28. Forcing a Garbage Collection • One can programmatically force a garbage collection using GC.Collect(). • Specifically: • Your application is about to enter into a block of code that you do not wish to be interrupted by a possible garbage collection. • Your application has just finished allocating an extremely large number of objects and you wish to remove as much of the acquired memory as possible. • If you determine it may be beneficial to have the garbage collector check for unreachable objects,

  29. To explicitly trigger a garbage collection: • static void Main(string[] args) • { • GC.Collect(); • GC.WaitForPendingFinalizers(); • } • Always make a call to GC.WaitForPendingFinalizers(). • It will suspend the calling “thread” during the collection process. • The GC.Collect() method can also be supplied a numerical value that identifies the oldest generation on which a garbage collection will be performed.

  30. Overriding System.Object.Finalize() • If a class makes use of unmanaged resources, to ensure that the underlying memory is released in a predictable manner, Finalize() can be used. • Configure your custom C# class types to override the Finalize() method, making use of the C++-like destructor syntax • The reason for this alternative form of overriding a virtual method is that when the C# compiler processes a destructor, it will automatically add information required within the Finalize() method

  31. Example : // Override System.Object.Finalize() via destructor syntax. class MyResourceWrapper { ~MyResourceWrapper() { // Clean up unmanaged resources. Beep when destroyed Console.Beep(); } }

  32. Examine this C# destructor using ildasm.exe The compiler inserts necessary error checking code. First, the code statements within the scope of your Finalize()method are placed within a try block. This bit of syntax is used to hold code statements that may trigger a runtime error (formally termed an exception) during their execution. The related finally block ensures that your base classes’ Finalize()method will always execute, regardless of any exceptions encountered within the try scope.

  33. Execute MyResourceWrapper , a system beep occurs When the application terminates, given that the CLR will automatically invoke finalizers upon AppDomain shutdown: static void Main(string[] args) { Console.WriteLine("***** Fun with Finalizers *****\n"); Console.WriteLine("Hit the return key to shut down this app"); Console.WriteLine("and force the GC to invoke Finalize()"); Console.WriteLine("for finalizable objects created in this AppDomain."); Console.ReadLine(); MyResourceWrapper rw = new MyResourceWrapper(); }

  34. Detailing the Finalization Process • When an object is allocated onto the managed heap, the runtime automatically determines if the object supports a custom Finalize()method. • If so, the object is marked as finalizable, and a pointer to this object is stored on an internal queue named the finalization queue. • The finalization queue is a table maintained by the garbage collector that points to each and every object that must be finalized before it is removed from the heap.

  35. Detailing the Finalization Process contd… • When the garbage collector determines it is time to free an object from memory, it examines each entry on the finalization queue, and copies the object off the heap to yet another managed structure termed the finalization reachable • At this point, a separate thread is spawned to invoke the Finalize() method for each object on the freachable table at the next garbage collection. • it will take at very least two garbage collections to truly finalize an object.

  36. Building Disposable Objects Disposable Objects is another technique used to handle an object’s cleanup. Unmanaged resources should be cleaned up ASAP As an alternative to overriding Finalize(), a class could implement the IDisposable interface, which defines a single method named Dispose(): public interface IDisposable { void Dispose(); }

  37. When the object user is finished using the object, it manually calls Dispose() before allowing the object reference to drop out of scope. In this way, the objects can perform any necessary cleanup of unmanaged resources without incurring the hit of being placed on the finalization queue and without waiting for the garbage collector to trigger the class’s finalization logic.

  38. Example : • An updated MyResourceWrapper class implements IDisposable, rather than overriding System.Object.Finalize(): • The object user should call this method when they are finished with the object. • public class MyResourceWrapper : IDisposable • public void Dispose() • { • // Clean up unmanaged resources here. • // Dispose other contained disposable objects. • } • }

  39. Dispose(): • releases the type’s unmanaged resources • should also call Dispose() on any other contained disposable methods. • Unlike Finalize(), it is safe to communicate with other managed objects within a Dispose() method. • The reason is simple: The garbage collector has no information about the IDisposable interface and will never call Dispose(). Therefore, when the object user calls this method, the object is still living a productive life on the managed heap and has access to all other heap-allocated objects.

  40. To Ensure the type supports the IDisposable interface. One can check programmatically using the is or as keywords public class Program { static void Main() { MyResourceWrapper rw = new MyResourceWrapper(); if (rw is IDisposable) rw.Dispose(); Console.ReadLine(); } }

  41. Reusing the C# using Keyword • Use structured exception handling to ensure the type’s Dispose()method is called. • Call the method in the event of a runtime exception handling a managed object that implements Idisposable: 

  42. static void Main(string[] args) { MyResourceWrapper rw = new MyResourceWrapper (); try { // Use the members of rw. } finally { // Always call Dispose(), error or not. rw.Dispose(); } }

  43. Example shows wrapping of disposable type within a try/catch/finally block just to ensure the Dispose() method is called. To achieve the same result in a much less obtrusive manner, C# supports a special bit of syntax that looks like this:  static void Main(string[] args) { // Dispose() is called automatically when the using scope exits. using(MyResourceWrapper rw = new MyResourceWrapper()) { // Use rw object. } }

  44. Building Finalizable and Disposable Types We have seen two different approaches to construct a class that cleans up internal unmanaged resources. Override System.Object.Finalize(). Using this technique, we have the peace of mind that comes with knowing the object cleans itself up when garbage collected (whenever that may be) without the need for user interaction. Implement IDisposable to provide a way for the object user to clean up the object as soon as it is finished. However, if the caller forgets to call Dispose(), the unmanaged resources may be held in memory indefinitely.

  45. Both techniques can be blended into a single class definition. • Advantages : • If the object user does remember to call Dispose(), one can inform the garbage collector to bypass the finalization process by calling GC.SuppressFinalize(). • If the object user forgets to call Dispose(), the object will eventually be finalized.

  46. Example of MyResourceWrapper, which is now finalizable and disposable: public class MyResourceWrapper : IDisposable { // The garbage collector will call this method if the object user forgets to call Dispose(). ~ MyResourceWrapper() { // Clean up any internal unmanaged resources. Do notcall Dispose() on any managed objects. } // The object user will call this method to clean up resources ASAP.

  47. public void Dispose() { // Clean up unmanaged resources here. Call Dispose() on other contained disposable objects. // No need to finalize if user called Dispose(), so suppress finalization. GC.SuppressFinalize(this); } } Dispose() method has been updated to call GC.SuppressFinalize(),which informs the CLR that it is no longer necessary to call the destructor when this object is garbage collected.

  48. A Formalized Disposal Pattern • Drawbacks of previous method. • The Finalize() and Dispose()method each have to clean up the same unmanaged resources. • This results in duplicate code. • you would like to make sure that the Finalize() method does not attempt to dispose of any managed objects, while the Dispose() method should do so. • Finally, you would also like to make sure that the object user can safely call Dispose() multiple times without error..

More Related