| EPackageRegistry in multi-threaded environment [message #498715] |
Wed, 18 November 2009 05:15  |
Eclipse User |
|
|
|
Hi,
we have a severe problem with the initialization of generated metamodels
with package dependencies between each other. During the initialization
of the packages (i.e. init() method) the global package registry is used
to resolve/initialize the dependent packages.
Example:
first metamodel:
public static FirstPackage init() {
// init FirstPackage ...
// Obtain or create and register interdependencies
// init SecondPackage
SecondPackageImpl sp =
(SecondPackageImpl)(EPackage.Registry.INSTANCE.getEPackage(S econdPackage.eNS_URI)
instanceof SecondPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(SecondPackage.eNS_URI ) :
SecondPackage.eINSTANCE);
}
second metamodel:
public static SecondPackage init() {
´ // init SecondPackage ...
// Obtain or create and register interdependencies
// init FirstPackage
FirstPackageImpl sp =
(FirstPackageImpl)(EPackage.Registry.INSTANCE.getEPackage(Fi rstPackage.eNS_URI)
instanceof FirstPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(FirstPackage.eNS_URI) :
FirstPackage.eINSTANCE);
}
Both initializations are performed in separated threads. Finally it ends
in a deadlock during the resolving of the involved EPackageDescriptors.
Both threads hang at the ensureClassInitialized() method:
Example Stack trace:
sun.misc.Unsafe.ensureClassInitialized(Native Method)
sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Unsa feFieldAccessorFactory.java:25)
sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFac tory.java:122)
java.lang.reflect.Field.acquireFieldAccessor(Field.java:918)
java.lang.reflect.Field.getFieldAccessor(Field.java:899)
java.lang.reflect.Field.get(Field.java:358)
org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescript or.getEPackage(RegistryReader.java:274)
org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage( EPackageRegistryImpl.java:133)
com.sap.metamodel.FirstPackageImpl.init(FirstPackageImpl.jav a:135)
Our solution attempts have been:
1. We already tried to modify our generated package classes to prevent
the deadlock (code reordering, synchronization), but without success and
then it happened also in a JST metamodel from eclipse.org...
2. We exchanged the global registry implementation by using the
appropriate system property. That worked, but it is the most undesirable
solution for us because there is no good point in time to set the
property programmatically. Setting the property at eclipse start is not
an option.
3. Due to the use of the global EPackageRegistry instance in the
generated metamodel package classes we do not see the possibility to use
a delegating package registry inside of resource sets.
Does somebody know how we can get this thread safe? Do we miss something?
Thanks alot!
Best regards,
Stefan and Martin
|
|
|
| Re: EPackageRegistry in multi-threaded environment [message #498728 is a reply to message #498715] |
Wed, 18 November 2009 07:27   |
Eclipse User |
|
|
|
Martin,
Comments below.
Martin Strenge wrote:
> Hi,
>
> we have a severe problem with the initialization of generated
> metamodels with package dependencies between each other.
You mean mutual dependencies right?
> During the initialization of the packages (i.e. init() method) the
> global package registry is used to resolve/initialize the dependent
> packages.
>
> Example:
>
> first metamodel:
> public static FirstPackage init() {
> // init FirstPackage ...
>
> // Obtain or create and register interdependencies
> // init SecondPackage
> SecondPackageImpl sp =
> (SecondPackageImpl)(EPackage.Registry.INSTANCE.getEPackage(S econdPackage.eNS_URI)
> instanceof SecondPackageImpl ?
> EPackage.Registry.INSTANCE.getEPackage(SecondPackage.eNS_URI ) :
> SecondPackage.eINSTANCE);
> }
>
> second metamodel:
> public static SecondPackage init() {
> ´ // init SecondPackage ...
>
> // Obtain or create and register interdependencies
> // init FirstPackage
> FirstPackageImpl sp =
> (FirstPackageImpl)(EPackage.Registry.INSTANCE.getEPackage(Fi rstPackage.eNS_URI)
> instanceof FirstPackageImpl ?
> EPackage.Registry.INSTANCE.getEPackage(FirstPackage.eNS_URI) :
> FirstPackage.eINSTANCE);
> }
>
> Both initializations are performed in separated threads. Finally it
> ends in a deadlock during the resolving of the involved
> EPackageDescriptors. Both threads hang at the ensureClassInitialized()
> method:
>
> Example Stack trace:
> sun.misc.Unsafe.ensureClassInitialized(Native Method)
> sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Unsa feFieldAccessorFactory.java:25)
>
> sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFac tory.java:122)
>
> java.lang.reflect.Field.acquireFieldAccessor(Field.java:918)
> java.lang.reflect.Field.getFieldAccessor(Field.java:899)
> java.lang.reflect.Field.get(Field.java:358)
> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescript or.getEPackage(RegistryReader.java:274)
>
> org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage( EPackageRegistryImpl.java:133)
>
> com.sap.metamodel.FirstPackageImpl.init(FirstPackageImpl.jav a:135)
Which JVM is being used?
>
>
> Our solution attempts have been:
>
> 1. We already tried to modify our generated package classes to prevent
> the deadlock (code reordering, synchronization), but without success
> and then it happened also in a JST metamodel from eclipse.org...
I've had many years of looking at different flavors of this type of
problem...
>
> 2. We exchanged the global registry implementation by using the
> appropriate system property. That worked, but it is the most
> undesirable solution for us because there is no good point in time to
> set the property programmatically. Setting the property at eclipse
> start is not an option.
How did that solve the problem? More often than not, a solution to one
problem causes new different problems...
>
> 3. Due to the use of the global EPackageRegistry instance in the
> generated metamodel package classes we do not see the possibility to
> use a delegating package registry inside of resource sets.
Nope.
>
>
> Does somebody know how we can get this thread safe? Do we miss something?
Of course avoiding mutually dependent packages is a good approach; after
all, they aren't independent... Another approach is to force
initialization early, i.e., before spawning various threads that will
simultaneous access the interdependent packages. I don't see a general
solution to the problem...
>
> Thanks alot!
>
> Best regards,
> Stefan and Martin
|
|
|
| Re: EPackageRegistry in multi-threaded environment [message #498746 is a reply to message #498728] |
Wed, 18 November 2009 08:59  |
Eclipse User |
|
|
|
Hi Ed,
thanks for the answers. Please see below.
Ed Merks wrote:
> Martin,
>
> Comments below.
>
> Martin Strenge wrote:
>> Hi,
>>
>> we have a severe problem with the initialization of generated
>> metamodels with package dependencies between each other.
> You mean mutual dependencies right?
Yes.
>> During the initialization of the packages (i.e. init() method) the
>> global package registry is used to resolve/initialize the dependent
>> packages.
>>
>> Example:
>>
>> first metamodel:
>> public static FirstPackage init() {
>> // init FirstPackage ...
>> // Obtain or create and register interdependencies
>> // init SecondPackage
>> SecondPackageImpl sp =
>> (SecondPackageImpl)(EPackage.Registry.INSTANCE.getEPackage(S econdPackage.eNS_URI)
>> instanceof SecondPackageImpl ?
>> EPackage.Registry.INSTANCE.getEPackage(SecondPackage.eNS_URI ) :
>> SecondPackage.eINSTANCE);
>> }
>>
>> second metamodel:
>> public static SecondPackage init() {
>> ´ // init SecondPackage ...
>> // Obtain or create and register interdependencies
>> // init FirstPackage
>> FirstPackageImpl sp =
>> (FirstPackageImpl)(EPackage.Registry.INSTANCE.getEPackage(Fi rstPackage.eNS_URI)
>> instanceof FirstPackageImpl ?
>> EPackage.Registry.INSTANCE.getEPackage(FirstPackage.eNS_URI) :
>> FirstPackage.eINSTANCE);
>> }
>>
>> Both initializations are performed in separated threads. Finally it
>> ends in a deadlock during the resolving of the involved
>> EPackageDescriptors. Both threads hang at the ensureClassInitialized()
>> method:
>>
>> Example Stack trace:
>> sun.misc.Unsafe.ensureClassInitialized(Native Method)
>> sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Unsa feFieldAccessorFactory.java:25)
>>
>> sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFac tory.java:122)
>>
>> java.lang.reflect.Field.acquireFieldAccessor(Field.java:918)
>> java.lang.reflect.Field.getFieldAccessor(Field.java:899)
>> java.lang.reflect.Field.get(Field.java:358)
>> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescript or.getEPackage(RegistryReader.java:274)
>>
>> org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage( EPackageRegistryImpl.java:133)
>>
>> com.sap.metamodel.FirstPackageImpl.init(FirstPackageImpl.jav a:135)
> Which JVM is being used?
Sun JDK 1.6.0_17
>>
>>
>> Our solution attempts have been:
>>
>> 1. We already tried to modify our generated package classes to prevent
>> the deadlock (code reordering, synchronization), but without success
>> and then it happened also in a JST metamodel from eclipse.org...
> I've had many years of looking at different flavors of this type of
> problem...
>>
>> 2. We exchanged the global registry implementation by using the
>> appropriate system property. That worked, but it is the most
>> undesirable solution for us because there is no good point in time to
>> set the property programmatically. Setting the property at eclipse
>> start is not an option.
> How did that solve the problem? More often than not, a solution to one
> problem causes new different problems...
Sure, it would avoid the deadlock just for this cause.
>>
>> 3. Due to the use of the global EPackageRegistry instance in the
>> generated metamodel package classes we do not see the possibility to
>> use a delegating package registry inside of resource sets.
> Nope.
>>
>>
>> Does somebody know how we can get this thread safe? Do we miss something?
> Of course avoiding mutually dependent packages is a good approach; after
> all, they aren't independent... Another approach is to force
> initialization early, i.e., before spawning various threads that will
> simultaneous access the interdependent packages. I don't see a general
> solution to the problem...
Early initialization is also an undesirable way because we like to do it
lazily, but seems currently to probably become the only solution.
Furthermore, we do not have control over all threads. Customers of our
framework (and also customers who don't use it) open threads as they
like and also access the package registry during bundle startup. Is
there a way to ensure that the package registry is build up before the
first access? Something like a "pre-early" startup phase, or may be by
deactivating the use of EPackageDescriptors?
>>
>> Thanks alot!
>>
>> Best regards,
>> Stefan and Martin
|
|
|
Powered by
FUDForum. Page generated in 0.02864 seconds