On 15.09.2014 15:16, Rick Hillegas wrote:
> On 9/12/14 7:29 AM, Rony G. Flatscher (Apache) wrote:
>> On 12.09.2014 15:29, Rick Hillegas wrote:
>>> On 9/12/14 3:37 AM, Rony G. Flatscher (Apache) wrote:
>>>> Hi there,
>>>>
>>>> tried to find this information on the Internet, but also in the derby 
>>>> wiki, but was not
>>>> successful so far, hence posting this question here where hopefully those 
>>>> in the know can help
>>>> out.
>>>>
>>>> Using derby from Oracle's JDK 7 distribution I encountered a problem and 
>>>> after a loong time of
>>>> research, testing, trials and errors I came up with a solution, but still 
>>>> do not understand the
>>>> reason for the problem!
>>>>
>>>> Here is the problem:
>>>>
>>>>      * having a class from a jar that is placed in one of the
>>>>        java.ext.dirs loading the derby JDBC  (to be precise:
>>>>        'org.apache.derby.jdbc.EmbeddedDriver' and then issuing a
>>>>        newInstance()) from the classpath works, but the subsequent
>>>>        
>>>> java.sql.DriverManager.getConnection('jdbc:derby:derbyDB;create=true',props)
>>>>        where 'props' is a java.util.Properties with "user1/user1" and
>>>>        "password/user1", yields:
>>>>        getCause(): [java.sql.SQLException: No suitable driver found for
>>>> jdbc:derby:derbyDB;create=true]
>>>>
>>>> The same program works without any changes,
>>>>
>>>>      * if the jar-file loading the derby JDBC is not in java.ext.dirs
>>>>        but on the classpath then it works
>>>>      * if the jar-file and derby.jar are both in java.ext.dirs then it
>>>>        works
>>>>
>>>> My question is, why is this so?
>>>>
>>>> (It seems to be the case that both, the Java class that loads the derby 
>>>> JDBC driver and the derby
>>>> JDBC driver, must use the same class loader, either a 
>>>> sun.misc.Launcher$AppClassLoader or a
>>>> sun.misc.Launcher$ExtClassLoader, which is very strange as I have not 
>>>> encountered a similar
>>>> requirement/behaviour in any other use case in the past years. The thread 
>>>> context class loader is
>>>> the application class loader which, if used, would have found derby.jar 
>>>> given on the classpath.)
>>>>
>>>> Is there any documentation that leads to an explanation about this 
>>>> behaviour somewhere? Are there
>>>> other Java infrastructures that have such a restriction that anyone is 
>>>> aware of?
>>>>
>>>> ---
>>>>
>>>> Background: I am authoring a scripting language binding for Java 
>>>> (BSF4ooRexx) and moving the
>>>> BSF4ooRexx jar to a Java extension directory makes it available to all 
>>>> Java applications
>>>> including the JavaPlugins for browsers. All test and sample programs work 
>>>> in this setup, except
>>>> for the sample program that demonstrates how easy it is to use derby via 
>>>> JDBC! :(
>>>>
>>>> ---
>>>>
>>>> Thankful for any pointer, hints, links, explanations that shed some light 
>>>> into this corner!
>>>>
>>>> ---rony
>>>>
>>>>
>>> Hi Rony,
>>>
>>> I have not been through this code recently. Maybe someone who has studied 
>>> it in detail can give
>>> you more information.
>>>
>>> I believe that putting Derby in lib/ext will make it impossible to unload 
>>> the Derby classes when
>>> you de-register the Derby driver. This is a feature of Derby which allows 
>>> Derby-powered components
>>> (including their class definitions) to be removed from memory when they are 
>>> not needed. If you put
>>> Derby in lib/ext, then the Derby class definitions will be loaded by the 
>>> extension class loader.
>>> Those definitions will remain loaded until the extension class loader is 
>>> garbage collected. I
>>> don't think there is a way to remove all references to the extension class 
>>> loader and so allow it
>>> to be garbage collected.
>>>
>>> It makes sense that Derby class loading won't work in a situation which 
>>> would prevent components
>>> from being removed.
>>>
>>> Note that the security implications of putting Derby in lib/ext are also 
>>> serious. By default,
>>> classes loaded by the extension class loader enjoy all permissions. You 
>>> would not want a browser
>>> plugin to be able to elevate its privileges by using Derby.
>>>
>>> Hope this helps,
>> Hi Rick,
>>
>> thank you!
>>
>> Actually, what I would be after is the following scenario: have the 
>> scirpting language binding in
>> lib/ext, but derby on classpath, and everything works.
>>
>> Having the scripting language binding and derby.jar on classpath works.
>>
>> Having the scripting language binding in lib/ext causes classes from that 
>> jar to load derby.jar,
>> then, when using DriveManager to get a connection to derby fails in this 
>> scenario, unfortunately.
>> (It is in this step attempting to get a connection, where the exception is 
>> thrown.) As a result it
>> is currently not possible to successfully use derby.jar (on classpath) in 
>> this desired scenario.
>>
>> I would go any length of miles to become able to do this successfully, 
>> rather then forcing the users
>> of the script programs to put derby.jar in lib/ext (or have to use 
>> -Djava.ext.dirs="..."), so would
>> be thankful for any insights and ideas.
>>
>> ---rony
>>
>> P.S.: Having both, the scripting language binding and derby.jar in lib/ext 
>> works too, but this is
>> not desired at all.
>>
>>
> Hi Rony,
>
> Can the scripting library get its hands on the class which is calling into 
> it? Maybe it could do
> something like the following to try to get the VM to load Derby with the 
> caller's ClassLoader:
>
>    Class.forName( "org.apache.derby.jdbc.EmbeddedDriver", true, 
> callingClass.getClassLoader() );
>
> Haven't tried this. Might be a waste of your time.
Thank you for this hint.

The problem is that the scripting library is in java.ext.dirs (to be available 
to all Java apps),
hence its classes are loaded with the extension class loader. At runtime of the 
scripts the script
library classes will interface with the JVM (e.g. loading classes, finding and 
invoking methods,
etc.), hence it is always the case that the calling class is from the script 
library and was loaded
with the extension class loader.

If the DriverManager would use the current thread's context class loader, then 
it should work, but
this seems to not be the case. It seems to be the case that it only uses the 
calling class class
loader“and if that is the case (and not regarded as an error), then one would 
be forced to move
'derby.jar' to java.ext.dirs, which for the very reasons you communicated would 
not be desired.

---rony

Reply via email to