BUG: Other Language Consumers Can Change a Final Field (325450)



The information in this article applies to:

  • Microsoft Visual J# .NET (2002)

This article was previously published under Q325450

SYMPTOMS

Final fields in Visual J# .NET assemblies are mutable from other .NET languages.

CAUSE

A bug in the Visual J# .NET compiler (Vjc.exe) and the Visual J# .NET Binary Converter Tool (Jbimp.exe) can cause other .NET language compilers not to recognize immutability in a Visual J# .NET field declaration.

RESOLUTION

To work around this problem, manually edit the MSIL of the Visual J# .NET assembly and add the initonly modifier to the .field declaration of the final field:
  1. At a Microsoft Visual Studio .NET command prompt, type the following command (use your Visual J# .dll file):
    ildasm /out=tmp.il js_server.dll
  2. Edit Tmp.il in a text editor and change the following line
    .field public class [vjslib]java.lang.Double d
    					
    to:
    .field public initonly class [vjslib]java.lang.Double d
    					
  3. Save the Tmp.il file.
  4. At a Visual Studio .NET command prompt, type the following command to produce your final Visual J# .NET .dll file:
    ilasm tmp.il /output=JS_Server.dll /dll /resource=tmp.res
    Note that changing the MSIL in this manner may cause verification errors, which may cause problems when it runs in a security context other than the local computer. If you do not see any verification issues after you apply the workaround, the bug has been cleanly removed without any side effects.

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

MORE INFORMATION

Steps to Reproduce the Behavior

  1. In Visual J# .NET, create a new Class Library project.
  2. Declare a final field of type java.lang.double in a Java language class and initialize to a value.
  3. Add a Console Application project for another language, such as Microsoft Visual C# .NET or Microsoft Visual Basic .NET.
  4. Add the Visual J# .NET project as a reference to the new project.
  5. Consume the final double by setting its value to something different from its initial value.
  6. Build the solution.
  7. Step into the console application in the debugger and watch the final field.
Note that the debugger shows the final double field to take the new value, even if you step into the Visual J# .NET code. Printing the double displays the new value.

For compile-time constants like primitive types and string, the values of these final fields in code that is compiled in Visual J# .NET are never changed in Visual J# .NET because these field references are replaced by their compile-time constant values while the code is compiled.
// Visual J# producer class
class Repro
{
	public final Double d = new Double(10.5);
 
	public void method()
	{
		System.out.println("value = " + d.toString());
	}

}
				
//C# consumer class
class CSUser 
{
	public static void Main() 
	{
		Repro r = new Repro();
		r.d = new java.lang.Double(5.1);
		r.method();
	}
}
				

Modification Type:MajorLast Reviewed:1/19/2004
Keywords:kbbug kbpending KB325450 kbAudDeveloper