org.springsource.loaded
Class ReloadableType

java.lang.Object
  extended by org.springsource.loaded.ReloadableType

public class ReloadableType
extends java.lang.Object

Represents a type that has been processed such that it can be reloaded at runtime.

Since:
0.5.0

Field Summary
 byte[] bytesInitial
          The bytes for the original implementation as first loaded, before rewriting
 byte[] bytesLoaded
          The bytes for the original implementation as first loaded, after rewriting
 java.lang.String dottedtypename
          The dotted typename
 byte[] interfaceBytes
          The bytes for the interface representing the first loaded implementation
 java.util.Map<java.lang.String,java.util.Map<java.lang.String,Invoker>> invokerCache_getDeclaredMethod
           
 java.util.Map<java.lang.String,java.util.Map<java.lang.String,Invoker>> invokerCache_getMethod
           
 java.util.List<Invoker> invokersCache_getDeclaredMethods
          Cache of the invokers used to answer getDeclaredMethods() call made on this type
 java.util.Collection<Invoker> invokersCache_getMethods
           
 java.lang.ref.Reference<java.lang.reflect.Method[]> jlClassGetDeclaredMethods_cache
           
 java.lang.ref.Reference<java.lang.reflect.Method[]> jlClassGetMethods_cache
           
static ReloadableType NOT_RELOADABLE_TYPE
           
static java.lang.ref.WeakReference<ReloadableType> NOT_RELOADABLE_TYPE_REF
           
 java.lang.String slashedtypename
          The slashed typename
 TypeDescriptor typedescriptor
          A type descriptor describing the shape of the type at first load
 TypeRegistry typeRegistry
          The registry maintaining this reloadable type
 
Constructor Summary
ReloadableType(java.lang.String dottedtypename, byte[] initialBytes, int id, TypeRegistry typeRegistry, TypeDescriptor typeDescriptor)
          Construct a new ReloadableType with the specified name and the specified initial bytecode.
 
Method Summary
 java.lang.Object cchanged(int ctorId)
           
 boolean cchanged(java.lang.String descriptor)
           
 int changed(int methodId)
          Check if the specified method is different to the original form from the type as loaded.
 void clearClassloaderLinks()
           
 int clinitchanged()
           
 __DynamicallyDispatchable determineDispatcher(java.lang.Object instance, java.lang.String nameAndDescriptor)
          Intended to handle dynamic dispatch.
 java.lang.Object fetchLatest()
           
 java.lang.Object fetchLatestIfExists(int methodId)
           
 FieldMember findInstanceField(java.lang.String name)
          Find the named instance field either on this reloadable type or on a reloadable supertype - it will not go into the non-reloadable types.
 FieldMember findStaticField(java.lang.String name)
          Search for a static field from this type upwards, as far as the topmost reloadable types.
 void fixupGroovyType()
          Groovy types need some extra fixup: they contain a callsite array that caches destinations for calls.
 java.lang.String getBaseName()
           
 byte[] getBytesInitial()
           
 byte[] getBytesLoaded()
           
 java.lang.Class<?> getClazz()
           
 MethodMember getConstructor(java.lang.String descriptor)
           
 MethodMember getCurrentConstructor(java.lang.String desc)
           
 MethodMember getCurrentMethod(java.lang.String name, java.lang.String descriptor)
          Gets the method corresponding to given name and descriptor, taking into consideration changes that have happened by reloading.
 __DynamicallyDispatchable getDispatcher()
           
 java.lang.Object getField(java.lang.Object instance, java.lang.String fieldname, boolean isStatic)
          Attempt to set the value of a field on an instance to the specified value.
 FieldReaderWriter getFieldInHierarchy(java.lang.String name)
           
 MethodMember getFromLatestByDescriptor(java.lang.String nameAndDescriptor)
           
 int getId()
           
 byte[] getInterfaceBytes()
           
 JavaMethodCache getJavaMethodCache()
           
 byte[] getLatestDispatcherBytes()
           
 java.lang.Class<?> getLatestDispatcherClass()
           
 java.lang.Object getLatestDispatcherInstance()
           
 java.lang.Object getLatestDispatcherInstance(boolean b)
           
 java.lang.String getLatestDispatcherName()
           
 byte[] getLatestExecutorBytes()
           
 java.lang.Class<?> getLatestExecutorClass()
           
 java.lang.String getLatestExecutorName()
           
 TypeDescriptor getLatestTypeDescriptor()
           
 CurrentLiveVersion getLiveVersion()
           
 MethodMember getMethod(java.lang.String nameAndDescriptor)
           
 MethodMember getMethod(java.lang.String name, java.lang.String descriptor)
          Gets the 'orignal' method corresponding to given name and method descriptor.
 java.lang.String getName()
           
 MethodMember getOriginalConstructor(java.lang.String desc)
           
 MethodMember getOriginalMethod(java.lang.String nameAndDescriptor)
          Gets the method corresponding to given name and descriptor, from the original type descriptor.
 java.lang.String getSlashedName()
           
 java.lang.String getSlashedSupertypeName()
           
 ReloadableType getSuperRtype()
           
 TypeDescriptor getTypeDescriptor()
           
 TypeRegistry getTypeRegistry()
           
 int getTypeRegistryId()
           
 boolean hasBeenReloaded()
           
 boolean hasFieldChangedInHierarchy(java.lang.String name)
          Want to check if this field looks the same as originally declared and is on the same type as it was
 boolean isResolved()
           
 boolean loadNewVersion(byte[] newbytedata)
           
 boolean loadNewVersion(java.lang.String versionsuffix, byte[] newbytedata)
          Load a new version of this type, using the specified suffix to tag the newly generated artifact class names.
 boolean loadNewVersion(java.lang.String versionsuffix, byte[] newbytedata, boolean shouldRerunStaticInitializer)
           
 FieldReaderWriter locateField(java.lang.String name)
          Find the field according to the rules of section 5.4.3.2 of the spec.
 void reloadMostRecentDispatcherAndExecutor()
           
 void rewriteCallSitesAndDefine()
          Rewrite the code for this reloadable type.
 void runStaticInitializer()
           
 void setField(java.lang.Object instance, java.lang.String fieldname, boolean isStatic, java.lang.Object newValue)
          Attempt to set the value of a field on an instance to the specified value.
 void setResolved()
           
 void setSuperclass(java.lang.Class<?> superclazz)
           
 boolean simulateReload()
           
 java.lang.String toString()
           
 void trackLiveInstance(java.lang.Object instance)
           
 FieldReaderWriter walk(java.lang.String name, TypeDescriptor typeDescriptor)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

typeRegistry

public TypeRegistry typeRegistry
The registry maintaining this reloadable type


dottedtypename

public final java.lang.String dottedtypename
The dotted typename


slashedtypename

public final java.lang.String slashedtypename
The slashed typename


bytesInitial

public byte[] bytesInitial
The bytes for the original implementation as first loaded, before rewriting


bytesLoaded

public byte[] bytesLoaded
The bytes for the original implementation as first loaded, after rewriting


interfaceBytes

public final byte[] interfaceBytes
The bytes for the interface representing the first loaded implementation


typedescriptor

public TypeDescriptor typedescriptor
A type descriptor describing the shape of the type at first load


invokersCache_getDeclaredMethods

public java.util.List<Invoker> invokersCache_getDeclaredMethods
Cache of the invokers used to answer getDeclaredMethods() call made on this type


invokersCache_getMethods

public java.util.Collection<Invoker> invokersCache_getMethods

invokerCache_getMethod

public java.util.Map<java.lang.String,java.util.Map<java.lang.String,Invoker>> invokerCache_getMethod

invokerCache_getDeclaredMethod

public java.util.Map<java.lang.String,java.util.Map<java.lang.String,Invoker>> invokerCache_getDeclaredMethod

NOT_RELOADABLE_TYPE

public static final ReloadableType NOT_RELOADABLE_TYPE

NOT_RELOADABLE_TYPE_REF

public static final java.lang.ref.WeakReference<ReloadableType> NOT_RELOADABLE_TYPE_REF

jlClassGetDeclaredMethods_cache

public java.lang.ref.Reference<java.lang.reflect.Method[]> jlClassGetDeclaredMethods_cache

jlClassGetMethods_cache

public java.lang.ref.Reference<java.lang.reflect.Method[]> jlClassGetMethods_cache
Constructor Detail

ReloadableType

public ReloadableType(java.lang.String dottedtypename,
                      byte[] initialBytes,
                      int id,
                      TypeRegistry typeRegistry,
                      TypeDescriptor typeDescriptor)
Construct a new ReloadableType with the specified name and the specified initial bytecode.

Parameters:
dottedtypename - the dotted name
initialBytes - the bytecode for the initial version
id - for this reloadable type, allocated by the registry
typeRegistry - the registry managing this type
typeDescriptor - the type descriptor (if it has already been worked out), otherwise null
Method Detail

getClazz

public java.lang.Class<?> getClazz()

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

getTypeDescriptor

public TypeDescriptor getTypeDescriptor()

getMethod

public MethodMember getMethod(java.lang.String name,
                              java.lang.String descriptor)
Gets the 'orignal' method corresponding to given name and method descriptor. This only considers methods that exist in the first (non-reloaded) version of the type.


getConstructor

public MethodMember getConstructor(java.lang.String descriptor)

loadNewVersion

public boolean loadNewVersion(byte[] newbytedata)

simulateReload

public boolean simulateReload()

loadNewVersion

public boolean loadNewVersion(java.lang.String versionsuffix,
                              byte[] newbytedata,
                              boolean shouldRerunStaticInitializer)

loadNewVersion

public boolean loadNewVersion(java.lang.String versionsuffix,
                              byte[] newbytedata)
Load a new version of this type, using the specified suffix to tag the newly generated artifact class names.


fixupGroovyType

public void fixupGroovyType()
Groovy types need some extra fixup:


getLatestDispatcherBytes

public byte[] getLatestDispatcherBytes()

getLatestDispatcherClass

public java.lang.Class<?> getLatestDispatcherClass()

getInterfaceBytes

public byte[] getInterfaceBytes()

getLatestDispatcherInstance

public java.lang.Object getLatestDispatcherInstance()

getLatestDispatcherInstance

public java.lang.Object getLatestDispatcherInstance(boolean b)

getLatestDispatcherName

public java.lang.String getLatestDispatcherName()

getBytesInitial

public byte[] getBytesInitial()

getBytesLoaded

public byte[] getBytesLoaded()

getLatestExecutorBytes

public byte[] getLatestExecutorBytes()

getLatestExecutorClass

public java.lang.Class<?> getLatestExecutorClass()

getLatestExecutorName

public java.lang.String getLatestExecutorName()

getCurrentMethod

public MethodMember getCurrentMethod(java.lang.String name,
                                     java.lang.String descriptor)
Gets the method corresponding to given name and descriptor, taking into consideration changes that have happened by reloading.


getOriginalMethod

public MethodMember getOriginalMethod(java.lang.String nameAndDescriptor)
Gets the method corresponding to given name and descriptor, from the original type descriptor.


getName

public java.lang.String getName()
Returns:
the dotted type name, eg. java.lang.String

getSlashedName

public java.lang.String getSlashedName()
Returns:
the slashed type name, eg. java/lang/String

getTypeRegistry

public TypeRegistry getTypeRegistry()
Returns:
the type registry responsible for this type

getTypeRegistryId

public int getTypeRegistryId()
Returns:
the reference number for the type registry responsible for this type

getId

public int getId()

rewriteCallSitesAndDefine

public void rewriteCallSitesAndDefine()
Rewrite the code for this reloadable type. This involves:


fetchLatest

public java.lang.Object fetchLatest()
Returns:
the most recent dispatcher

hasBeenReloaded

public boolean hasBeenReloaded()

getLiveVersion

public CurrentLiveVersion getLiveVersion()

cchanged

public boolean cchanged(java.lang.String descriptor)

cchanged

public java.lang.Object cchanged(int ctorId)

changed

public int changed(int methodId)
Check if the specified method is different to the original form from the type as loaded.

Parameters:
methodId - the ID of the method currently executing
Returns:
0 if the method cannot have changed. 1 if the method has changed. 2 if the method has been deleted in a new version.

clinitchanged

public int clinitchanged()

fetchLatestIfExists

public java.lang.Object fetchLatestIfExists(int methodId)

getSlashedSupertypeName

public java.lang.String getSlashedSupertypeName()

getDispatcher

public __DynamicallyDispatchable getDispatcher()

determineDispatcher

public __DynamicallyDispatchable determineDispatcher(java.lang.Object instance,
                                                     java.lang.String nameAndDescriptor)
Intended to handle dynamic dispatch. This will determine the right type to handle the specified method and return a dispatcher that can handle it.

Parameters:
instance -
nameAndDescriptor - an encoded method name and descriptor, e.g. foo(Ljava/langString;)V

getBaseName

public java.lang.String getBaseName()
Returns:
type name without the package prefix

getLatestTypeDescriptor

public TypeDescriptor getLatestTypeDescriptor()

getFromLatestByDescriptor

public MethodMember getFromLatestByDescriptor(java.lang.String nameAndDescriptor)

getMethod

public MethodMember getMethod(java.lang.String nameAndDescriptor)

getCurrentConstructor

public MethodMember getCurrentConstructor(java.lang.String desc)

getOriginalConstructor

public MethodMember getOriginalConstructor(java.lang.String desc)

getJavaMethodCache

public JavaMethodCache getJavaMethodCache()

findInstanceField

public FieldMember findInstanceField(java.lang.String name)
Find the named instance field either on this reloadable type or on a reloadable supertype - it will not go into the non-reloadable types. This method also avoids interfaces because it is looking for instance fields. This is slightly naughty but if we assume the code we are reloading is valid code, it should never be referring to interface fields.

Parameters:
name - the name of the field to locate
Returns:
the FieldMember or null if the field is not found

findStaticField

public FieldMember findStaticField(java.lang.String name)
Search for a static field from this type upwards, as far as the topmost reloadable types. This is searching for a field, it is not checking the result. It is up to the caller to check they have not ended up with an instance field and throw the appropriate exception.

Parameters:
name - the name of the field to look for
Returns:
a FieldMember for the named field or null if not found

setField

public void setField(java.lang.Object instance,
                     java.lang.String fieldname,
                     boolean isStatic,
                     java.lang.Object newValue)
              throws java.lang.IllegalAccessException
Attempt to set the value of a field on an instance to the specified value.

Parameters:
instance - the object upon which to set the field (maybe null for static fields)
fieldname - the name of the field
-
newValue - the new value to put into the field
Throws:
java.lang.IllegalAccessException

getField

public java.lang.Object getField(java.lang.Object instance,
                                 java.lang.String fieldname,
                                 boolean isStatic)
                          throws java.lang.IllegalAccessException
Attempt to set the value of a field on an instance to the specified value. Simply locate the field, which returns an object capable of reading/writing it, then use that to retrieve the value.

Parameters:
instance - the object upon which to set the field (maybe null for static fields)
fieldname - the name of the field
-
newValue - the new value to put into the field
Throws:
java.lang.IllegalAccessException

locateField

public FieldReaderWriter locateField(java.lang.String name)
Find the field according to the rules of section 5.4.3.2 of the spec.


walk

public FieldReaderWriter walk(java.lang.String name,
                              TypeDescriptor typeDescriptor)

hasFieldChangedInHierarchy

public boolean hasFieldChangedInHierarchy(java.lang.String name)
Want to check if this field looks the same as originally declared and is on the same type as it was


getFieldInHierarchy

public FieldReaderWriter getFieldInHierarchy(java.lang.String name)

clearClassloaderLinks

public void clearClassloaderLinks()

reloadMostRecentDispatcherAndExecutor

public void reloadMostRecentDispatcherAndExecutor()

trackLiveInstance

public void trackLiveInstance(java.lang.Object instance)

runStaticInitializer

public void runStaticInitializer()

isResolved

public boolean isResolved()

setResolved

public void setResolved()

setSuperclass

public void setSuperclass(java.lang.Class<?> superclazz)

getSuperRtype

public ReloadableType getSuperRtype()