New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrency Issue Loading Ops and OperatorImpl #1237

Closed
franciscospaeth opened this Issue Mar 5, 2015 · 2 comments

Comments

Projects
None yet
3 participants
@franciscospaeth

Whenever com.mysema.query.types.OperatorImpl and com.mysema.query.types.Ops are loaded simultaneously loaded a deadlock is reached.

The following code could be used to reproduce the issue:

import org.junit.Test;

import com.mysema.query.jpa.impl.JPAQuery;

public class CycleClassInitDependencyTest {

    @Test(timeout = 2000)
    public void test() throws InterruptedException {

        // If class is loaded before hand it will work for example:
        // System.out.println(Ops.DateTimeOps.DATE);

        // each thread wants
        Thread t1 = new Thread(new LoadClassRunnable("com.mysema.query.types.OperatorImpl"));
        Thread t2 = new Thread(new LoadClassRunnable("com.mysema.query.types.Ops"));
        t1.start();
        t2.start();

        // trying to create anything depending on Ops class for instance:
        // JPAQuery -> JPQLTemplates -> Ops
        new JPAQuery();

    }

    public class LoadClassRunnable implements Runnable {

        private String classToLoad;

        public LoadClassRunnable(String classToLoad) {
            this.classToLoad = classToLoad;
        }

        public void run() {
            try {
                Class.forName(classToLoad);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

    }

}

A jstack relevant part of the execution of code exposed above is:

"OpslLoading        " prio=10 tid=0x00007f47a4003000 nid=0x2dd3 in Object.wait() [0x00007f47b7cfb000]
   java.lang.Thread.State: RUNNABLE
    at com.mysema.query.types.Ops.<clinit>(Ops.java:30)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:188)
    at CycleClassInitDependencyTest$LoadClassRunnable.run(CycleClassInitDependencyTest.java:37)
    at java.lang.Thread.run(Thread.java:722)

"OperatorImplLoading" prio=10 tid=0x00007f47a4001800 nid=0x2dd2 in Object.wait() [0x00007f47b7dfb000]
   java.lang.Thread.State: RUNNABLE
    at sun.misc.Unsafe.ensureClassInitialized(Native Method)
    at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
    at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:140)
    at java.lang.reflect.Field.acquireFieldAccessor(Field.java:949)
    at java.lang.reflect.Field.getFieldAccessor(Field.java:930)
    at java.lang.reflect.Field.get(Field.java:372)
    at com.mysema.query.types.OperatorImpl.<clinit>(OperatorImpl.java:42)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:188)
    at CycleClassInitDependencyTest$LoadClassRunnable.run(CycleClassInitDependencyTest.java:37)
    at java.lang.Thread.run(Thread.java:722)

"Thread-0" prio=10 tid=0x00007f47ec205000 nid=0x2dd1 in Object.wait() [0x00007f47b7efc000]
   java.lang.Thread.State: RUNNABLE
    at com.mysema.query.types.Templates.<init>(Templates.java:50)
    at com.mysema.query.types.Templates.<init>(Templates.java:38)
    at com.mysema.query.types.Templates.<clinit>(Templates.java:27)
    at com.mysema.query.jpa.impl.JPAQuery.<init>(JPAQuery.java:35)
    at CycleClassInitDependencyTest.test(CycleClassInitDependencyTest.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.FailOnTimeout$StatementThread.run(FailOnTimeout.java:74)
@Shredder121

This comment has been minimized.

Show comment
Hide comment
@Shredder121

Shredder121 Mar 5, 2015

Member

I have successfully reproduced this case, I will push your test case this afternoon.

@timowest I already tried some synchronization, but if one thread holds the lock for Ops, and the other for OperatorImpl. we have a problem (since they are dependent on each other).

Member

Shredder121 commented Mar 5, 2015

I have successfully reproduced this case, I will push your test case this afternoon.

@timowest I already tried some synchronization, but if one thread holds the lock for Ops, and the other for OperatorImpl. we have a problem (since they are dependent on each other).

@timowest

This comment has been minimized.

Show comment
Hide comment
@timowest

timowest Mar 5, 2015

Member

This could be solved by getting rid of the OPS cache in OperationImpl and reading the OperatorImpl in deserialization via the Operator.id, since it is always FQCN#staticField.

Querydsl 4.0.0 won't have that issue since the Operator instances are enums.

Member

timowest commented Mar 5, 2015

This could be solved by getting rid of the OPS cache in OperationImpl and reading the OperatorImpl in deserialization via the Operator.id, since it is always FQCN#staticField.

Querydsl 4.0.0 won't have that issue since the Operator instances are enums.

@timowest timowest changed the title from Concurrency Issue Loading Opts and OperatorImpl to Concurrency Issue Loading Ops and OperatorImpl Mar 5, 2015

Shredder121 added a commit that referenced this issue Mar 6, 2015

Shredder121 added a commit that referenced this issue Mar 6, 2015

@timowest timowest added this to the 3.6.3 milestone Mar 6, 2015

@timowest timowest closed this Mar 11, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment