2002-12-18 19:00:25 +03:00
/ *
2004-03-20 16:25:08 +03:00
Copyright ( C ) 2002 , 2003 , 2004 Jeroen Frijters
2002-12-18 19:00:25 +03:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
Jeroen Frijters
jeroen @frijters . net
* /
using System ;
2003-01-06 19:30:09 +03:00
using System.Reflection ;
2004-03-20 16:25:08 +03:00
using System.Diagnostics ;
2002-12-18 19:00:25 +03:00
2004-09-09 15:17:55 +04:00
namespace IKVM.Runtime
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
public class ByteCodeHelper
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object multianewarray ( RuntimeTypeHandle typeHandle , int [ ] lengths )
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
for ( int i = 0 ; i < lengths . Length ; i + + )
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
if ( lengths [ i ] < 0 )
{
throw JavaException . NegativeArraySizeException ( ) ;
}
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
return MultianewarrayHelper ( Type . GetTypeFromHandle ( typeHandle ) . GetElementType ( ) , lengths , 0 ) ;
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
private static object MultianewarrayHelper ( Type elemType , int [ ] lengths , int index )
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
object o = Array . CreateInstance ( elemType , lengths [ index + + ] ) ;
if ( index < lengths . Length )
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
elemType = elemType . GetElementType ( ) ;
object [ ] a = ( object [ ] ) o ;
for ( int i = 0 ; i < a . Length ; i + + )
{
a [ i ] = MultianewarrayHelper ( elemType , lengths , index ) ;
}
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
return o ;
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicMultianewarray ( RuntimeTypeHandle type , string clazz , int [ ] lengths )
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicMultianewarray" ) ;
TypeWrapper wrapper = LoadTypeWrapper ( type , clazz ) ;
return multianewarray ( wrapper . TypeAsArrayType . TypeHandle , lengths ) ;
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicNewarray ( int length , RuntimeTypeHandle type , string clazz )
{
Profiler . Count ( "DynamicNewarray" ) ;
if ( length < 0 )
{
throw JavaException . NegativeArraySizeException ( ) ;
}
TypeWrapper wrapper = LoadTypeWrapper ( type , clazz ) ;
return Array . CreateInstance ( wrapper . TypeAsArrayType , length ) ;
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static void DynamicAastore ( object arrayref , int index , object val , RuntimeTypeHandle type , string clazz )
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicAastore" ) ;
// TODO do we need to load the type here?
( ( Array ) arrayref ) . SetValue ( val , index ) ;
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicAaload ( object arrayref , int index , RuntimeTypeHandle type , string clazz )
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicAaload" ) ;
// TODO do we need to load the type here?
return ( ( Array ) arrayref ) . GetValue ( index ) ;
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
private static FieldWrapper GetFieldWrapper ( TypeWrapper thisType , RuntimeTypeHandle type , string clazz , string name , string sig , bool isStatic )
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
TypeWrapper caller = ClassLoaderWrapper . GetWrapperFromType ( Type . GetTypeFromHandle ( type ) ) ;
TypeWrapper wrapper = LoadTypeWrapper ( type , clazz ) ;
2004-10-04 23:30:53 +04:00
FieldWrapper field = wrapper . GetFieldWrapper ( name , sig ) ;
2004-09-09 15:17:55 +04:00
if ( field = = null )
{
throw JavaException . NoSuchFieldError ( clazz + "." + name ) ;
}
// TODO check loader constraints
if ( field . IsStatic ! = isStatic )
{
throw JavaException . IncompatibleClassChangeError ( clazz + "." + name ) ;
}
if ( field . IsAccessibleFrom ( caller , thisType ) )
{
return field ;
}
throw JavaException . IllegalAccessError ( field . DeclaringType . Name + "." + name ) ;
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicGetfield ( object obj , string name , string sig , RuntimeTypeHandle type , string clazz )
{
Profiler . Count ( "DynamicGetfield" ) ;
return GetFieldWrapper ( ClassLoaderWrapper . GetWrapperFromType ( obj . GetType ( ) ) , type , clazz , name , sig , false ) . GetValue ( obj ) ;
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicGetstatic ( string name , string sig , RuntimeTypeHandle type , string clazz )
{
Profiler . Count ( "DynamicGetstatic" ) ;
return GetFieldWrapper ( null , type , clazz , name , sig , true ) . GetValue ( null ) ;
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static void DynamicPutfield ( object obj , object val , string name , string sig , RuntimeTypeHandle type , string clazz )
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicPutfield" ) ;
FieldWrapper fw = GetFieldWrapper ( ClassLoaderWrapper . GetWrapperFromType ( obj . GetType ( ) ) , type , clazz , name , sig , false ) ;
if ( fw . IsFinal )
{
throw JavaException . IllegalAccessError ( "Field " + fw . DeclaringType . Name + "." + fw . Name + " is final" ) ;
}
fw . SetValue ( obj , val ) ;
2004-08-17 13:05:21 +04:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static void DynamicPutstatic ( object val , string name , string sig , RuntimeTypeHandle type , string clazz )
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicPutstatic" ) ;
FieldWrapper fw = GetFieldWrapper ( null , type , clazz , name , sig , true ) ;
if ( fw . IsFinal )
{
throw JavaException . IllegalAccessError ( "Field " + fw . DeclaringType . Name + "." + fw . Name + " is final" ) ;
}
fw . SetValue ( null , val ) ;
2004-08-17 13:05:21 +04:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
// the sole purpose of this method is to check whether the clazz can be instantiated (but not to actually do it)
[DebuggerStepThroughAttribute]
public static void DynamicNewCheckOnly ( RuntimeTypeHandle type , string clazz )
2004-01-11 16:14:42 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicNewCheckOnly" ) ;
TypeWrapper wrapper = LoadTypeWrapper ( type , clazz ) ;
2004-10-19 17:43:55 +04:00
if ( wrapper . IsAbstract )
2004-09-09 15:17:55 +04:00
{
throw JavaException . InstantiationError ( clazz ) ;
}
2004-01-11 16:14:42 +03:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
private static TypeWrapper LoadTypeWrapper ( RuntimeTypeHandle type , string clazz )
2003-05-30 16:08:59 +04:00
{
2004-09-09 15:17:55 +04:00
try
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
TypeWrapper context = ClassLoaderWrapper . GetWrapperFromType ( Type . GetTypeFromHandle ( type ) ) ;
TypeWrapper wrapper = context . GetClassLoader ( ) . LoadClassByDottedNameFast ( clazz ) ;
if ( wrapper = = null )
{
throw JavaException . NoClassDefFoundError ( clazz ) ;
}
if ( ! wrapper . IsAccessibleFrom ( context ) )
{
2005-02-02 18:11:26 +03:00
throw JavaException . IllegalAccessError ( "Try to access class " + wrapper . Name + " from class " + context . Name ) ;
2004-09-09 15:17:55 +04:00
}
wrapper . Finish ( ) ;
return wrapper ;
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
catch ( RetargetableJavaException x )
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
throw x . ToJava ( ) ;
2004-08-17 13:05:21 +04:00
}
2004-12-21 13:26:51 +03:00
catch ( Exception x )
{
// HACK we need to convert a ClassNotFoundException into a NoClassDefFoundError
if ( x . GetType ( ) . FullName = = "java.lang.ClassNotFoundException" )
{
throw JavaException . NoClassDefFoundError ( x . Message ) ;
}
throw ;
}
2003-05-30 16:08:59 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicClassLiteral ( RuntimeTypeHandle type , string clazz )
2004-01-11 16:14:42 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicClassLiteral" ) ;
2004-12-21 17:59:29 +03:00
return LoadTypeWrapper ( type , clazz ) . ClassObject ;
2004-01-11 16:14:42 +03:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicCast ( object obj , RuntimeTypeHandle type , string clazz )
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicCast" ) ;
if ( ! DynamicInstanceOf ( obj , type , clazz ) )
{
throw JavaException . ClassCastException ( ClassLoaderWrapper . GetWrapperFromType ( obj . GetType ( ) ) . Name ) ;
}
return obj ;
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static bool DynamicInstanceOf ( object obj , RuntimeTypeHandle type , string clazz )
2003-01-06 19:30:09 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicInstanceOf" ) ;
TypeWrapper wrapper = LoadTypeWrapper ( type , clazz ) ;
TypeWrapper other = ClassLoaderWrapper . GetWrapperFromType ( obj . GetType ( ) ) ;
return other . IsAssignableTo ( wrapper ) ;
2003-01-06 19:30:09 +03:00
}
2004-09-09 15:17:55 +04:00
private static MethodWrapper GetMethodWrapper ( TypeWrapper thisType , RuntimeTypeHandle type , string clazz , string name , string sig , bool isStatic )
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
TypeWrapper caller = ClassLoaderWrapper . GetWrapperFromType ( Type . GetTypeFromHandle ( type ) ) ;
TypeWrapper wrapper = LoadTypeWrapper ( type , clazz ) ;
2005-01-03 11:26:21 +03:00
MethodWrapper mw = wrapper . GetMethodWrapper ( name , sig , false ) ;
2004-09-09 15:17:55 +04:00
if ( mw = = null )
{
throw JavaException . NoSuchMethodError ( clazz + "." + name + sig ) ;
}
// TODO check loader constraints
if ( mw . IsStatic ! = isStatic )
{
throw JavaException . IncompatibleClassChangeError ( clazz + "." + name ) ;
}
if ( mw . IsAccessibleFrom ( caller , thisType = = null ? wrapper : thisType ) )
{
return mw ;
}
throw JavaException . IllegalAccessError ( clazz + "." + name + sig ) ;
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicInvokeSpecialNew ( RuntimeTypeHandle type , string clazz , string name , string sig , object [ ] args )
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicInvokeSpecialNew" ) ;
return GetMethodWrapper ( null , type , clazz , name , sig , false ) . Invoke ( null , args , false ) ;
2004-08-17 13:05:21 +04:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicInvokestatic ( RuntimeTypeHandle type , string clazz , string name , string sig , object [ ] args )
{
Profiler . Count ( "DynamicInvokestatic" ) ;
return GetMethodWrapper ( null , type , clazz , name , sig , true ) . Invoke ( null , args , false ) ;
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicInvokevirtual ( object obj , RuntimeTypeHandle type , string clazz , string name , string sig , object [ ] args )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicInvokevirtual" ) ;
2005-02-02 18:11:26 +03:00
return GetMethodWrapper ( ClassLoaderWrapper . GetWrapperFromType ( obj . GetType ( ) ) , type , clazz , name , sig , false ) . Invoke ( obj , args , false ) ;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static Type DynamicGetTypeAsExceptionType ( RuntimeTypeHandle type , string clazz )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicGetTypeAsExceptionType" ) ;
return LoadTypeWrapper ( type , clazz ) . TypeAsExceptionType ;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static int f2i ( float f )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if ( f < = int . MinValue )
{
return int . MinValue ;
}
if ( f > = int . MaxValue )
{
return int . MaxValue ;
}
if ( f ! = f )
{
return 0 ;
}
return ( int ) f ;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static long f2l ( float f )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if ( f < = long . MinValue )
{
return long . MinValue ;
}
if ( f > = long . MaxValue )
{
return long . MaxValue ;
}
if ( f ! = f )
{
return 0 ;
}
return ( long ) f ;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static int d2i ( double d )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if ( d < = int . MinValue )
{
return int . MinValue ;
}
if ( d > = int . MaxValue )
{
return int . MaxValue ;
}
if ( d ! = d )
{
return 0 ;
}
return ( int ) d ;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static long d2l ( double d )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if ( d < = long . MinValue )
{
return long . MinValue ;
}
if ( d > = long . MaxValue )
{
return long . MaxValue ;
}
if ( d ! = d )
{
return 0 ;
}
return ( long ) d ;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
// This is used by static JNI and synchronized methods that need a class object
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static object GetClassFromTypeHandle ( RuntimeTypeHandle typeHandle )
2003-02-27 19:41:47 +03:00
{
2004-10-19 17:43:55 +04:00
return Util . GetClassFromTypeHandle ( typeHandle ) ;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy ( object src , int srcStart , object dest , int destStart , int len )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if ( src ! = dest )
{
// NOTE side effect of GetTypeHandle call is null check for src and dest (it
// throws an ArgumentNullException)
// Since constructing a Type object is expensive, we use Type.GetTypeHandle and
// hope that it is implemented in a such a way that it is more efficient than
// Object.GetType()
try
{
RuntimeTypeHandle type_src = Type . GetTypeHandle ( src ) ;
RuntimeTypeHandle type_dst = Type . GetTypeHandle ( dest ) ;
if ( type_src . Value ! = type_dst . Value )
{
if ( len > = 0 )
{
try
{
// since Java strictly defines what happens when an ArrayStoreException occurs during copying
// and .NET doesn't, we have to do it by hand
object [ ] src1 = src as object [ ] ;
object [ ] dst1 = dest as object [ ] ;
if ( src1 ! = null & & dst1 ! = null )
{
for ( ; len > 0 ; len - - )
{
dst1 [ destStart + + ] = src1 [ srcStart + + ] ;
}
}
else
{
// one (or both) of the arrays might be a value type array
Array src2 = ( Array ) src ;
Array dst2 = ( Array ) dest ;
// we don't want to allow copying a primitive into an object array!
if ( ClassLoaderWrapper . GetWrapperFromType ( src2 . GetType ( ) . GetElementType ( ) ) . IsPrimitive | |
ClassLoaderWrapper . GetWrapperFromType ( dst2 . GetType ( ) . GetElementType ( ) ) . IsPrimitive )
{
throw JavaException . ArrayStoreException ( ) ;
}
for ( ; len > 0 ; len - - )
{
dst2 . SetValue ( src2 . GetValue ( srcStart + + ) , destStart + + ) ;
}
}
return ;
}
catch ( InvalidCastException )
{
throw JavaException . ArrayStoreException ( ) ;
}
}
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
}
catch ( ArgumentNullException )
{
throw JavaException . NullPointerException ( ) ;
}
}
try
{
Array . Copy ( ( Array ) src , srcStart , ( Array ) dest , destStart , len ) ;
}
catch ( ArgumentNullException )
{
throw JavaException . NullPointerException ( ) ;
}
catch ( ArgumentException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( InvalidCastException )
{
throw JavaException . ArrayStoreException ( ) ;
}
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_8 ( Array src , int srcStart , Array dest , int destStart , int len )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
try
{
checked
{
Buffer . BlockCopy ( src , srcStart < < 3 , dest , destStart < < 3 , len < < 3 ) ;
return ;
}
}
catch ( ArgumentNullException )
{
throw JavaException . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
2003-02-27 19:41:47 +03:00
}
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_4 ( Array src , int srcStart , Array dest , int destStart , int len )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
try
{
checked
{
Buffer . BlockCopy ( src , srcStart < < 2 , dest , destStart < < 2 , len < < 2 ) ;
return ;
}
}
catch ( ArgumentNullException )
{
throw JavaException . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_2 ( Array src , int srcStart , Array dest , int destStart , int len )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
try
{
checked
{
Buffer . BlockCopy ( src , srcStart < < 1 , dest , destStart < < 1 , len < < 1 ) ;
return ;
}
}
catch ( ArgumentNullException )
{
throw JavaException . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_1 ( Array src , int srcStart , Array dest , int destStart , int len )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
try
{
Buffer . BlockCopy ( src , srcStart , dest , destStart , len ) ;
return ;
}
catch ( ArgumentNullException )
{
throw JavaException . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw JavaException . ArrayIndexOutOfBoundsException ( ) ;
}
2003-02-27 19:41:47 +03:00
}
2005-02-11 17:46:58 +03:00
public static void VerboseCastFailure ( RuntimeTypeHandle typeHandle , object obj )
{
throw IKVM . Internal . JVM . Library . newClassCastException ( String . Format ( "Object of type \"{0}\" cannot be cast to \"{1}\"" , obj . GetType ( ) . AssemblyQualifiedName , Type . GetTypeFromHandle ( typeHandle ) . AssemblyQualifiedName ) ) ;
}
2003-02-27 19:41:47 +03:00
}
2002-12-18 19:00:25 +03:00
}