ColdFusion Structures under the hood
I have been having a lot of fun lately digging around the internals of the Adobe CF Server. With my new found knowledge I thought I would dig around structures. So how can you find out what the implementation of a structure is? Well first off you need to find out the name of the class and to do this it gets pretty tricky. Looking at this we can tell the class for the struct is coldfusion.runtime.Struct, as I said it can get pretty tricky (ha). So what that does is return back an the class Object which has some pretty handy methods in it. There are methods that can tell you what the package is, what the super class is as well as methods, fields & constructors. If we look at the following code we can see that there are easy ways to output all of this information.
//methods
methods = class.getMethods();
writeOutput("Methods" & "
");
for(x = 1; x LTE arrayLen(methods); ++x) {
writeOutput(methods[x] & "
");
}
writeOutput("
");
If we run the previous code we get the following output.
Class: class coldfusion.runtime.Struct
Superclass: class coldfusion.util.FastHashtable
Package: package coldfusion.runtime
Fields
public static final int coldfusion.monitor.memory.MemoryTrackable.NO_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.LOCAL_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.ARGUMENTS_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.THREAD_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.PAGE_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.THIS_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.REQUEST_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.SESSION_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.APPLICATION_SCOPE
public static final int coldfusion.monitor.memory.MemoryTrackable.SERVER_SCOPE
Constructors
public coldfusion.runtime.Struct(int)
public coldfusion.runtime.Struct(coldfusion.runtime.StructWrapper)
public coldfusion.runtime.Struct()
Methods
public java.lang.Object coldfusion.runtime.Struct.clone()
public synchronized java.lang.Object coldfusion.runtime.Struct.get(java.lang.Object)
public synchronized java.util.Map coldfusion.runtime.Struct.duplicate(java.util.IdentityHashMap) throws java.lang.IllegalAccessException
public java.lang.Object coldfusion.runtime.Struct.writeReplace()
public java.util.WeakHashMap coldfusion.runtime.Struct.getStructWrapperMap()
public static boolean coldfusion.runtime.Struct.IsStruct(java.lang.Object)
public static boolean coldfusion.runtime.Struct.StructAppend(java.util.Map,java.util.Map,boolean)
public static boolean coldfusion.runtime.Struct.StructClear(java.util.Map)
public static java.util.Map coldfusion.runtime.Struct.StructCopy(java.util.Map) throws java.lang.Throwable
public static int coldfusion.runtime.Struct.StructCount(java.util.Map)
public static boolean coldfusion.runtime.Struct.StructDelete(java.util.Map,java.lang.String,boolean)
public static java.lang.Object coldfusion.runtime.Struct.StructFind(java.util.Map,java.lang.String)
public static coldfusion.runtime.Array coldfusion.runtime.Struct.StructFindKey(java.util.Map,java.lang.String,java.lang.String)
public static coldfusion.runtime.Array coldfusion.runtime.Struct.StructFindValue(java.util.Map,java.lang.String,java.lang.String)
public static boolean coldfusion.runtime.Struct.StructInsert(java.util.Map,java.lang.String,java.lang.Object,boolean)
public static boolean coldfusion.runtime.Struct.StructIsEmpty(java.util.Map)
public static coldfusion.runtime.Array coldfusion.runtime.Struct.StructKeyArray(java.util.Map)
public static java.lang.String coldfusion.runtime.Struct.StructKeyList(java.util.Map,java.lang.String)
public static java.lang.String coldfusion.runtime.Struct.StructKeyList(java.util.Map)
public static coldfusion.util.FastHashtable coldfusion.runtime.Struct.StructNew()
public static coldfusion.runtime.Array coldfusion.runtime.Struct.StructSort(java.util.Map,java.lang.String,java.lang.String,java.lang.String)
public int coldfusion.runtime.Struct.getScopeType()
public coldfusion.monitor.memory.MemoryTrackerProxy coldfusion.runtime.Struct.getMemoryTrackerProxy()
public void coldfusion.runtime.Struct.setMemoryTrackerProxy(coldfusion.monitor.memory.MemoryTrackerProxy)
public java.util.Iterator coldfusion.runtime.Struct.valuesIterator()
public synchronized java.lang.Object coldfusion.util.FastHashtable.put(java.lang.Object,java.lang.Object)
public synchronized void coldfusion.util.FastHashtable.clear()
public synchronized boolean coldfusion.util.FastHashtable.contains(java.lang.Object)
public synchronized boolean coldfusion.util.FastHashtable.isEmpty()
public synchronized void coldfusion.util.FastHashtable.putAll(java.util.Map)
public synchronized int coldfusion.util.FastHashtable.size()
public synchronized java.lang.Object coldfusion.util.FastHashtable.remove(java.lang.Object)
public synchronized java.util.Enumeration coldfusion.util.FastHashtable.elements()
public synchronized java.util.Enumeration coldfusion.util.FastHashtable.keys()
public synchronized boolean coldfusion.util.FastHashtable.containsKey(java.lang.Object)
public int coldfusion.util.CaseInsensitiveMap.hashCode()
public boolean coldfusion.util.CaseInsensitiveMap.equals(java.lang.Object)
public java.lang.String coldfusion.util.CaseInsensitiveMap.toString()
public java.util.Set coldfusion.util.CaseInsensitiveMap.entrySet()
public java.util.Collection coldfusion.util.CaseInsensitiveMap.values()
public java.util.Set coldfusion.util.CaseInsensitiveMap.keySet()
public boolean coldfusion.util.CaseInsensitiveMap.containsValue(java.lang.Object)
public java.util.Map coldfusion.util.CaseInsensitiveMap.duplicate() throws java.lang.IllegalAccessException
public final native java.lang.Class java.lang.Object.getClass()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
Now we can't really see the code but we can see what methods are available to us. The first thought is well is there anything I really care about? That was my first thought as well so lets go through a couple things I found.
The first thing i noticed is that there was a method name hashCode() that returns an integer. Usually a class will override the equals method to allow for comparison of objects. So usually if the objects are equally these hash codes are the same. Have your ever needed to see if two structures contained the same keys/values? Well using our new knowledge this should be possible. The following tells us that our structures are equal, if you change the 2nd loop to a max of 20, they come out not equal. Also its helpful if you check out the hashCode() for each as they will be the same here.
Another useful method is the toString method. Most objects override this method and this one gives us a great print out.
If we run the code above we get a nice print out that looks like this.
{1={1.0},2={2.0},3={3.0},4={4.0},5={5.0},6={6.0},7={7.0},8={8.0},9={9.0},10={10.0}}
The final one is just something I thought I would throw out. I have not found an improvement in performance but its there so I thought I would show it to you. If you wanted to print out all of the values you would usually just loop over the collection and print out each keys value. If you look at our methods list there is one called valuesIterator(). This method returns us an iterator that has 2 handy methods for looping. Here is a quick example of how to run over the values. Please remember this is just here for fun.
While some of you may question my madness I really have no answer. I saw a wonderful presentation at CFUnited only to come home on a treasure hunt. You should be able to start looking around on your own, happy hunting!
