Ehcache Core
  1. Ehcache Core
  2. EHC-926

UnsupportedOperationException at CacheKeySet.toArray

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: 2 Major 2 Major
    • Resolution: Unresolved
    • Affects Version/s: 2.5.1
    • Fix Version/s: None
    • Component/s: ehcache-core
    • Labels:
      None
    • Terracotta Target:
      Ehcache 2.5.x

      Description

      I make a simple 2 cache node simulation. First starting one node and then after some time starting another one. When second node starts it throws a warning during bootstrap:

      21:10:39.404 [Bootstrap Thread for cache getOrtVisningListeHent] WARN n.s.e.d.RMIBootstrapCacheLoader - Error asynchronously performing bootstrap. The cause was: Error bootstrapping from remote peer. Message was: null
      net.sf.ehcache.distribution.RemoteCacheException: Error bootstrapping from remote peer. Message was: null
      at net.sf.ehcache.distribution.RMIBootstrapCacheLoader.doLoad(RMIBootstrapCacheLoader.java:176)
      at net.sf.ehcache.distribution.RMIBootstrapCacheLoader$BootstrapThread.run(RMIBootstrapCacheLoader.java:107)
      Caused by: java.lang.UnsupportedOperationException: null
      at net.sf.ehcache.store.CacheKeySet.toArray(CacheKeySet.java:121)
      at net.sf.ehcache.util.SetAsList.toArray(SetAsList.java:83)
      at java.util.ArrayList.<init>(ArrayList.java:136)
      at net.sf.ehcache.distribution.RMICachePeer.getKeys(RMICachePeer.java:125)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:592)
      at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294)
      at sun.rmi.transport.Transport$1.run(Transport.java:154)
      at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
      at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
      at java.lang.Thread.run(Thread.java:595)
      at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247)
      at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)
      at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126)
      at net.sf.ehcache.distribution.RMICachePeer_Stub.getKeys(Unknown Source)
      at net.sf.ehcache.distribution.RMIBootstrapCacheLoader.doLoad(RMIBootstrapCacheLoader.java:146)
      ... 1 common frames omitted

      After that notmal replication between 2 nodes works fine. Ehcache configuration is attached to the issue.

      1. CacheKeySet.java
        6 kB
        Andrey Adamovich
      2. ehcache-current.xml
        3 kB
        Andrey Adamovich

        Activity

        Hide
        Andrey Adamovich added a comment -

        The problem seems to come from the fact that net.sf.ehcache.store.CacheKeySet does not implement one of the overloads of toArray method:

        CacheKeySet.java
            /**
             * {@inheritDoc}
             */
            public <T> T[] toArray(final T[] a) {
                throw new UnsupportedOperationException();
            }
        

        After I added an implementation and recompiled ehcache-core-2.5.1.jar the problem seems to go away. Here is the implementation:

        CacheKeySet.java
            /**
             * {@inheritDoc}
             */
            public <T> T[] toArray(final T[] a) {
                Iterator<E> iterator = this.iterator();
                for (int i = 0; i < a.length; i++) {
                    a[i] = (T) iterator.next();        
                }
                return a;
            }
        
        Show
        Andrey Adamovich added a comment - The problem seems to come from the fact that net.sf.ehcache.store.CacheKeySet does not implement one of the overloads of toArray method: CacheKeySet.java /** * {@inheritDoc} */ public <T> T[] toArray( final T[] a) { throw new UnsupportedOperationException(); } After I added an implementation and recompiled ehcache-core-2.5.1.jar the problem seems to go away. Here is the implementation: CacheKeySet.java /** * {@inheritDoc} */ public <T> T[] toArray( final T[] a) { Iterator<E> iterator = this .iterator(); for ( int i = 0; i < a.length; i++) { a[i] = (T) iterator.next(); } return a; }
        Hide
        Andrey Adamovich added a comment -

        Full version of updated CacheKeySet.java

        Show
        Andrey Adamovich added a comment - Full version of updated CacheKeySet.java
        Hide
        Tim Eck added a comment -

        That implementation of toArray() isn't quite right. You can't assume the passed in array is the correct size and is supposed to null terminate the array if it is too big.

        Also if someone goes to implement this for real I think it is also wrong to get a this.size() and then start to iterate and assume you'll get the same number of elements from both (in the face of concurrent updates)

        Show
        Tim Eck added a comment - That implementation of toArray() isn't quite right. You can't assume the passed in array is the correct size and is supposed to null terminate the array if it is too big. Also if someone goes to implement this for real I think it is also wrong to get a this.size() and then start to iterate and assume you'll get the same number of elements from both (in the face of concurrent updates)
        Hide
        Andrey Adamovich added a comment -

        If array size is bigger than CacheKeySet, then it can be achieved with the following code:

        CacheKeySet.java
            /**
             * {@inheritDoc}
             */
            public <T> T[] toArray(final T[] a) {
                Iterator<E> iterator = this.iterator();
                for (int i = 0; i < a.length; i++) {
                    if (iterator.hasNext()) {
                       a[i] = (T) iterator.next();        
                    } else {
                       a[i] = null;
                    } 
                }
                return a;
            }
        
        Show
        Andrey Adamovich added a comment - If array size is bigger than CacheKeySet, then it can be achieved with the following code: CacheKeySet.java /** * {@inheritDoc} */ public <T> T[] toArray( final T[] a) { Iterator<E> iterator = this .iterator(); for ( int i = 0; i < a.length; i++) { if (iterator.hasNext()) { a[i] = (T) iterator.next(); } else { a[i] = null ; } } return a; }
        Hide
        Tim Eck added a comment -

        sorry, wasn't challenging you to fix it

        Was just making a note to whoever might go to add an implementation here.

        Show
        Tim Eck added a comment - sorry, wasn't challenging you to fix it Was just making a note to whoever might go to add an implementation here.
        Hide
        Parameswaran Thangavel added a comment -

        Hi,
        I am using ehcache-core-2.5.1.jar and faced above error.

        Interestingly, I am getting above error (warning) only when I point my java application to JVM 1.5, if it point it to 1.6 then i am not getting above error.

        So, my observation is

        For JVM 1.5 "public <T> T[] toArray(final T[] a) " method is invoked and I am getting UnsupportedOperationException but for JVM 1.6 "public Object[] toArray()" method is invoked and it works fine.

        Any idea or thought on why the method that get invoked varies as per the JVM version?

            /**
             * {@inheritDoc}
             */
            public Object[] toArray() {
                List<E> list = new ArrayList<E>();
                for (E e : this) {
                    list.add(e);
                }
                return list.toArray();
            }
        
            /**
             * {@inheritDoc}
             */
            public <T> T[] toArray(final T[] a) {
                throw new UnsupportedOperationException();
            }
        
        Show
        Parameswaran Thangavel added a comment - Hi, I am using ehcache-core-2.5.1.jar and faced above error. Interestingly, I am getting above error (warning) only when I point my java application to JVM 1.5, if it point it to 1.6 then i am not getting above error. So, my observation is For JVM 1.5 "public <T> T[] toArray(final T[] a) " method is invoked and I am getting UnsupportedOperationException but for JVM 1.6 "public Object[] toArray()" method is invoked and it works fine. Any idea or thought on why the method that get invoked varies as per the JVM version? /** * {@inheritDoc} */ public Object [] toArray() { List<E> list = new ArrayList<E>(); for (E e : this ) { list.add(e); } return list.toArray(); } /** * {@inheritDoc} */ public <T> T[] toArray( final T[] a) { throw new UnsupportedOperationException(); }
        Hide
        Tim Eck added a comment -

        that 1.5 vs. 1.6 behavior is very unusual. I can't explain that. If you have a test program that demostrates the problem I could get to the bottom of it.

        The decision of what method to call (at least by signature) is made at compile time

        Show
        Tim Eck added a comment - that 1.5 vs. 1.6 behavior is very unusual. I can't explain that. If you have a test program that demostrates the problem I could get to the bottom of it. The decision of what method to call (at least by signature) is made at compile time

          People

          • Assignee:
            Chris Dennis
            Reporter:
            Andrey Adamovich
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: