Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » Modeling (top-level project) » StackOverflowError on EPackage Initialization
StackOverflowError on EPackage Initialization [message #619490] Mon, 22 March 2010 14:12
Paul Hoser is currently offline Paul Hoser
Messages: 4
Registered: March 2010
Junior Member
Hi Everybody!

I have a problem with my EMF model. I am getting a StackOverflowError
when my EPackages are initialized. My model is rather large. It consists
of about 150 packages each containing at least one classifier.

Within the init() method of an EPackage the inter-depending EPackages
are initialized recursively. The interdenpendencies of an EPackage are
calculated by the GenPackageImpl.DependencyHelper. The algorithm looks
like this:

public DependencyHelper()
{
...
interDependencies = new ArrayList<GenPackage>();
collectPackages(interDependencies, getGenModel().getGenPackages(), -1);
interDependencies.remove(GenPackageImpl.this);
...
}



protected void collectPackages(List<GenPackage> result,
List<GenPackage> genPackages, int depth)
{
if (depth == 0) return;

for (GenPackage genPackage : genPackages)
{
if (genPackage.hasClassifiers())
{
result.add(genPackage);
collectPackages(result, genPackage.getNestedGenPackages(),
depth - 1);
}
else
{
collectPackages(result, genPackage.getNestedGenPackages(), depth);
}
}
}


This basically means that all EPackages within the model which contain
classifiers are inter-depedenent to each other. If we had an example
model containing three packages (MyPackage, YourPackage, OurPackage) we
would get generated code like this:



public class MyPackageImpl extends EPackageImpl implements MyPackage
{
...
public static MyPackage init() {
...
YourPackageImpl theYourPackage = (YourPackageImpl)
(EPackage.Registry.INSTANCE.getEPackage(YourPackage.eNS_URI) instanceof
YourPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(YourPackage.eNS_URI) :
YourPackage.eINSTANCE);
OurPackageImpl theOurPackage = (OurPackageImpl)
(EPackage.Registry.INSTANCE.getEPackage(OurPackage.eNS_URI) instanceof
OurPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(OurPackage.eNS_URI) :
OurPackage.eINSTANCE);
...
}
...
}

public class YourPackageImpl extends EPackageImpl implements YourPackage
{
...
public static YourPackage init() {
...
MyPackageImpl theMyPackage = (MyPackageImpl)
(EPackage.Registry.INSTANCE.getEPackage(MyPackage.eNS_URI) instanceof
MyPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(MyPackage.eNS_URI) :
MyPackage.eINSTANCE);
OurPackageImpl theOurPackage = (OurPackageImpl)
(EPackage.Registry.INSTANCE.getEPackage(OurPackage.eNS_URI) instanceof
OurPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(OurPackage.eNS_URI) :
OurPackage.eINSTANCE);
...
}
...
}

public class OurPackageImpl extends EPackageImpl implements OurPackage
{
...
public static OurPackage init() {
...
MyPackageImpl theMyPackage = (MyPackageImpl)
(EPackage.Registry.INSTANCE.getEPackage(MyPackage.eNS_URI) instanceof
MyPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(MyPackage.eNS_URI) :
MyPackage.eINSTANCE);
YourPackageImpl theYourPackage = (YourPackageImpl)
(EPackage.Registry.INSTANCE.getEPackage(YourPackage.eNS_URI) instanceof
YourPackageImpl ?
EPackage.Registry.INSTANCE.getEPackage(YourPackage.eNS_URI) :
YourPackage.eINSTANCE);

...
}
...
}


If we would now access any of these EPackages, for instance the
MyPackage, via the eINSTANCE field all three packages would be
initialized recursively and we would get the following stacktrace:

OurPackageImpl.init() line: 655
OurPackage.<clinit>() line: 75

Unsafe.ensureClassInitialized(Class) line: not available [native
method]
UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean) line: 25
ReflectionFactory.newFieldAccessor(Field, boolean) line: 122
Field.acquireFieldAccessor(boolean) line: 918
Field.getFieldAccessor(Object) line: 899
Field.get(Object) line: 358
RegistryReader$EPackageDescriptor.getEPackage() line: 274
EPackageRegistryImpl.getEPackage(String) line: 133
YourPackageImpl.init() line: 698
YourPackage.<clinit>() line: 78

Unsafe.ensureClassInitialized(Class) line: not available [native method]
UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean) line: 25
ReflectionFactory.newFieldAccessor(Field, boolean) line: 122
Field.acquireFieldAccessor(boolean) line: 918
Field.getFieldAccessor(Object) line: 899
Field.get(Object) line: 358
RegistryReader$EPackageDescriptor.getEPackage() line: 274
EPackageRegistryImpl.getEPackage(String) line: 133
MyPackageImpl.init() line: 714
MyPackage.<clinit>() line: 77


If this is performed not only for three packages (as listed above) but
for 150 the 64K of stack size are not sufficient anymore.



SOLUTION PROPOSALS & QUESTIONS
------------------------------

A possible solution would be to simply increase the stack size via the
Xss VM argument. Unfortunately, this does not work for Java 1.5 and I
need to support Java 1.5.

see also: http://bugs.sun.com/view_bug.do?bug_id=6316197


I thought of some options for solving this issue. Unfortunately, my
knowledge of EMF internals is too little to decide if these approaches
are reasonable or not.

1. Reducing the number of interdependencies
The algorithm for calculating the set of inter-depending EPackages could
be optimized.
- Is this a reasonable approach?
- Or is it necessary to always initialize all EPackages as soon as one
EPackage is initialized?
- What is the interdependency initialization required for?

2. Make the Interdependency Initialization Non-Recursive
It could be possible to set a "inDependencyInitialization" flag which is
set by the first EPackage initialized. Subsequent calls to init() in
other EPackages could skip their interdependency initialization.
- Again, is this reasonable?
- Would this approach lead to concurrency problems?

3. Reduce the number of method-calls per initialization
As the EPackageDescriptor accesses the eINSTANCE field within its
getEPackage() method via reflection each EPackage initialization
requires 10 method calls. This number could be reduced by providing a
public getInstance() method for accessing the EPackage instance.
- Why was this complicated way of accessing the EPackage instance via
the eINSTANCE field chosen?
- Could this be substituted by a getInstance() method or would this
introduce concurrency problems?

I would really like to better understand the rational behind the design
decisions made for the EPackage initialization and would appreciate any
feedback on the above proposed solutions and their corresponding questions.

Of course if anyone has a better idea on how to solve this StackOverflow
problem, it is more than welcome.

Thanks and best regards,

Paul
Previous Topic:[Graphiti Project] - Any news about??
Next Topic:StackOverflowError on EPackage Initialization
Goto Forum:
  


Current Time: Sat Sep 20 16:04:23 GMT 2014

Powered by FUDForum. Page generated in 0.01518 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software