I've since resolved the issue. At the risk of answering my own question, I'll post my solution here to help anyone else who gets the same issue.
It was actually a genuine ClassCastException, and nothing to do with multiple classloaders (I overlooked the simple issue!). We are calling the following Oracle-specific API:
CLOB.createTemporary(connection, cacheFlag, duration);
Although this takes a plain old JDBC "Connection" as a parameter, the Oracle code within this method then tries to cast it to an "OracleConnection" - to get access to the Oracle-specific functionality. This implementation is vulnerable to any connection pooling mechanism that uses a wrapper class (such as JBoss's).
The solution is to check if the Connection is actually a "org.jboss.resource.adapter.jdbc.WrappedConnection" and if so call "getUnderlyingConnection()" (which if you're using the Oracle driver will then return the underlying OracleConnection instance), then pass that to the Oracle API.
I can see I'm going to need similar code for any other pooling mechanisms on other app servers that use wrapper classes. Ho hum!