Miscellaneous Debris

Avner Kashtan's Frustrations and Exultations
Static Constructor throws the same exception again and again

Here’s a little gotcha I ran into today – if you have code in a class’s static constructor that throws an exception, we will get a TypeInitializationException with the original exception as the InnerException – so far, nothing new.

However, if we keep on calling methods on that object, we’ll keep receiving TypeInitializationExceptions. If it cannot be initialized, it cannot be called. Every time we try, we’ll receive the exact same exception. However, the static ctor will not be called again. What appears to happen is that the CLR caches the TypeInitializationException object itself, InnerException included, and rethrows it whenever the type is called.

What are the ramifications? Well, we received an OutOfMemoryException in our static ctor, but the outer exception was caught and tried again. So we got an OutOfMemoryException again, even though the memory problem was behind us, which sent us down the wrong track of looking for persistent memory problems. Theoretically, it could also be a leak – the inner exception holding some sort of reference that is never released, but that’s an edge case.

Here’s some code to illustrate the problem. The output clearly shows that while we wait a second between calls, the inner exception contains the time of the original exception, not any subsequent calls. Debugging also shows that the static ctor is called only once.

   1:  class Program
   2:  {
   3:      static void Main(string[] args)
   4:      {
   5:   
   6:          for (int i = 0; i < 5; i++)
   7:          {
   8:              try
   9:              {
  10:                  Thread.Sleep(1000);
  11:                  StaticClass.Method();
  12:   
  13:              }
  14:              catch (Exception ex)
  15:              {
  16:                  Console.WriteLine(ex.InnerException.Message);
  17:              }
  18:          }
  19:   
  20:          Console.ReadLine();
  21:      }
  22:  }
  23:   
  24:  static class StaticClass
  25:  {
  26:      static StaticClass()
  27:      {
  28:          throw new Exception("Exception thrown at " + DateTime.Now.ToString());
  29:      }
  30:   
  31:      public static void Method()
  32:      { }
  33:   
  34:  }

Published Tuesday, December 16, 2008 12:17 PM by Avner Kashtan

Filed under: , ,

Comments

# re: Static Constructor throws the same exception again and again@ Tuesday, December 16, 2008 9:05 AM

I can't find the official doc, but I've always believed that a static initialization exception rendered they type unusable for the life of the app domain.

AndrewSeven

# re: Static Constructor throws the same exception again and again@ Tuesday, December 16, 2008 9:59 AM

It does, if by "unusable" you mean "throws a TypeInitializationException for the life of the app domain" and by "throws a TypeInitializationException" you mean "throws THE SAME TypeInitializationException instance". :)

Avner Kashtan

# Fique por dentro Constructor &raquo; Blog Archive &raquo; Static Constructor throws the same exception again and again &#8230;@ Monday, January 12, 2009 8:30 PM

Pingback from  Fique por dentro Constructor  &raquo; Blog Archive   &raquo; Static Constructor throws the same exception again and again &#8230;

Fique por dentro Constructor » Blog Archive » Static Constructor throws the same exception again and again …

# Fique por dentro Constructor &raquo; Blog Archive &raquo; Static Constructor throws the same exception again and again &#8230;@ Saturday, January 17, 2009 4:35 AM

Pingback from  Fique por dentro Constructor  &raquo; Blog Archive   &raquo; Static Constructor throws the same exception again and again &#8230;

Fique por dentro Constructor » Blog Archive » Static Constructor throws the same exception again and again …

# re: Static Constructor throws the same exception again and again@ Tuesday, March 10, 2009 5:23 AM

Even I think they are unusable for the rest of the life of app domain.

Visual Guard for Sybase ASE

Leave a Comment

(required) 
(required) 
(optional)
(required)