Skip to content
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

StackOverflowError when sending my last Bitcoins #402

Closed
mikehearn opened this issue Jun 11, 2015 · 18 comments
Closed

StackOverflowError when sending my last Bitcoins #402

mikehearn opened this issue Jun 11, 2015 · 18 comments
Labels
Enhancement Request for enhancement, or the implementation of one

Comments

@mikehearn
Copy link
Member

Originally reported on Google Code with ID 36

Have a look at

http://blockexplorer.com/testnet/address/mukdwUGeAjJiyDsg4pGU9S3xaQbJfa6JFe

After I was entering the last transaction (05acd31488ab73fb901ac8882989042ae288b2ccae8e6b6e96838ba517b9123b)
which was using all my remaining 5 Bitcoins, the client immediately crashed (I guess
while saving the wallet).

Note that I have applied the patch from issue 35.


E/AndroidRuntime(24167): java.lang.StackOverflowError
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.dumpCycle(ObjectOutputStream.java:471)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1739)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1205)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime(24167):    at java.util.ArrayList.writeObject(ArrayList.java:651)
E/AndroidRuntime(24167):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(24167):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime(24167):    at java.util.ArrayList.writeObject(ArrayList.java:651)
E/AndroidRuntime(24167):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(24167):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime(24167):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)

Reported by andreas.schildbach on 2011-07-02 07:38:46

@mikehearn mikehearn added Enhancement Request for enhancement, or the implementation of one Priority-Medium labels Jun 11, 2015
@mikehearn
Copy link
Member Author

That's interesting. Is it the full stack trace? Seems the bottom may have been truncated.

Presumably this is a bug in the Java serialization implementation (on Android only?).
I don't think it's supposed to be possible to crash the serializer like that.

If some platforms have a buggy serialization engine, that's a strike against using
it for wallets.

Reported by hearn@google.com on 2011-07-02 08:52:28

@mikehearn
Copy link
Member Author

Yes, it is truncated at the bottom. The above output is followed by these lines:

E/AndroidRuntime(24167):        at java.io
W/ActivityManager(  103):   Force finishing activity de.schildbach.wallet/.WalletActivity

I would very much like to send you the wallet, but unfortunately I still haven't had
the fix in place that put the wallet in a world readable location for testnet. (I have
fixed this now. I promise ;-)

Reported by andreas.schildbach on 2011-07-02 09:08:40

@mikehearn
Copy link
Member Author

This issue was closed by revision r124.

Reported by hearn@google.com on 2011-07-06 12:12:27

  • Status changed: Fixed

@mikehearn
Copy link
Member Author

Oops, typo closed wrong bug.

Reported by hearn@google.com on 2011-07-06 12:14:15

  • Status changed: Accepted

@mikehearn
Copy link
Member Author

Ah, got it again. Attaching the wallet this time.

Reported by andreas.schildbach on 2011-07-07 23:51:44


- _Attachment: [wallet-testnet](https://storage.googleapis.com/google-code-attachments/bitcoinj/issue-36/comment-5/wallet-testnet)_

@mikehearn
Copy link
Member Author

And here is a bit more of stack trace this time:

W/InputManagerService(  103): Starting input on non-focused client com.android.internal.view.IInputMethodClient$Stub$Proxy@406515a0
(uid=10050 pid=4407)
D/dalvikvm(  174): GC_EXTERNAL_ALLOC freed 75K, 43% free 3640K/6343K, external 4957K/4964K,
paused 52ms
D/dalvikvm(  174): GC_EXTERNAL_ALLOC freed 91K, 44% free 3610K/6343K, external 5219K/5502K,
paused 50ms
I/System.out( 4407): about to send 22000000 (BTC 0.22) to mjcZDSDtroERr1jnnZdwjWhTjjVbhGW86H
W/System.err( 4407): 262418 [main] INFO com.google.bitcoin.core.Wallet - Creating send
tx to mjcZDSDtroERr1jnnZdwjWhTjjVbhGW86H for 0.22
W/System.err( 4407): 262420 [main] INFO com.google.bitcoin.core.Wallet -   with 0.78
coins change
D/dalvikvm( 4407): GC_CONCURRENT freed 1104K, 50% free 3678K/7239K, external 2785K/3201K,
paused 2ms+8ms
W/System.err( 4407): 262791 [main] INFO com.google.bitcoin.core.Wallet -   created
c43b589872623fb7c0edbfc026b7e7c9282b65de9cc488f2a62f5982b718fce2
I/System.out( 4407): discovering peers
W/System.err( 4407): 263350 [backgroundThread] WARN com.google.bitcoin.discovery.IrcDiscovery
- IRC nick does not parse as base58: u2f43AKh726St3P
I/System.out( 4407): 59 peers discovered, took 639 ms
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@40616c58
W/System.err( 4407): 263439 [main] INFO com.google.bitcoin.core.Wallet - confirmSend
of c43b589872623fb7c0edbfc026b7e7c9282b65de9cc488f2a62f5982b718fce2
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@4057b0f8
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@406302e0
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@40610540
I/dalvikvm( 4407): threadid=1: stack overflow on call to Ljava/util/IdentityHashMap;.findIndex:ILL
I/dalvikvm( 4407):   method requires 32+20+12=64 bytes, fp is 0x4214a310 (16 left)
I/dalvikvm( 4407):   expanding stack end (0x4214a300 to 0x4214a000)
I/dalvikvm( 4407): Shrank stack (to 0x4214a300, curFrame is 0x4214a4ac)
D/AndroidRuntime( 4407): Shutting down VM
W/dalvikvm( 4407): threadid=1: thread exiting with uncaught exception (group=0x40015560)
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@4061be78
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@40616c58
E/AndroidRuntime( 4407): FATAL EXCEPTION: main
E/AndroidRuntime( 4407): java.lang.StackOverflowError
E/AndroidRuntime( 4407):    at java.util.IdentityHashMap.get(IdentityHashMap.java:371)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.dumpCycle(ObjectOutputStream.java:471)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1739)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1205)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime( 4407):    at java.util.ArrayList.writeObject(ArrayList.java:651)
E/AndroidRuntime( 4407):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 4407):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1205)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:1143)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:413)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1241)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
E/AndroidRuntime( 4407):    at java.util.HashSet.writeObject(HashSet.java:192)
E/AndroidRuntime( 4407):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 4407):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219)
E/AndroidRuntime( 4407):    at java.io.ObjectOutputStream.write
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@4057b0f8
I/System.out( 4407): broadcasting to com.google.bitcoin.core.Peer@406302e0
D/dalvikvm( 4407): GC_CONCURRENT freed 1178K, 51% free 3672K/7367K, external 2817K/3201K,
paused 2ms+6ms
W/ActivityManager(  103):   Force finishing activity de.schildbach.wallet/.SendCoinsActivity

Reported by andreas.schildbach on 2011-07-07 23:52:54

@mikehearn
Copy link
Member Author

Another one of these StackOverflowErrors:

http://i.imgur.com/vA7lc.jpg

Reported by andreas.schildbach on 2011-07-15 00:17:07

@mikehearn
Copy link
Member Author

This issue has got nothing to do with "sending the last coins".

Looks like this is a quite old problem with Java serialization:

http://bugs.sun.com/view_bug.do?bug_id=4152790

http://stackoverflow.com/questions/438875/stackoverflowerror-when-serializing-an-object-in-java

Let me quote the stack overflow page:

    Java serialization keeps a record of every object written to a stream. If the same
object is encountered a second time, only a reference to it is written to the stream,
and not a second copy of the object; so circular references aren't the problem here.

    But serialization is vulnerable to stack overflow for certain kinds of structures;
for example, a long linked list with no special writeObject() methods will be serialized
by recursively writing each link. If you've got a 100,000 links, you're going to try
to use 100,000 stack frames, and quite likely fail with a StackOverflowError.

    It's possible to define a writeObject() method for such a list class that, when
the first link is serialized, simply walks the list and serializes each link iteratively;
this will prevent the default recursive mechanism from being used.

Reported by andreas.schildbach on 2011-07-16 17:17:56

@mikehearn
Copy link
Member Author

Have you got a more recent example wallet? It seems the one that's attached no longer
deserializes.

Reported by hearn@google.com on 2011-07-18 21:07:39

@mikehearn
Copy link
Member Author

If you can reproduce the issue, you could try just winding up the stack size for now.
It's obviously only a temporary fix but might let you deserialize wallets that got
too complicated for the stack size allowed. See the Thread constructor that lets you
control the size.

I played about with stuffing wallets full of transactions on the desktop JRE but couldn't
reproduce the problem.

Reported by hearn@google.com on 2011-07-18 22:14:43

@mikehearn
Copy link
Member Author

I've upped stack to 64 kb (from 8 kb? - don't know) and this seeems to do the trick
with my problem-ridden testnet wallet.

Reported by andreas.schildbach on 2011-07-18 23:24:28

@mikehearn
Copy link
Member Author

I just hit the stack size boundary again with my test wallet with these two addresses:

http://blockexplorer.com/testnet/address/mwhsLCBMmTXgzjMXhteKk63siFRsCboVEm
http://blockexplorer.com/testnet/address/mx6WWrWgYHhHevB3KJqduRU8qpaopdWBJF

About 50 sends and 50 receives is quite a lot for the average user, but some power
users might hit the limit soon.

I'll extend to 96 kb stack...

Reported by andreas.schildbach on 2011-09-05 20:31:09

@mikehearn
Copy link
Member Author

Is increasing the stack size a viable medium-term workaround, or should the priority
on this be increased?

Reported by miron@google.com on 2011-10-14 20:35:35

  • Status changed: New
  • Blocked on: #

@mikehearn
Copy link
Member Author

I have pretty much no idea of how high stack size can be set on Android without side
effects.

I'd rather increase priority; not having a stable and extendable wallet format is a
blocker for several other enhancements as well:

- storing creation timestamps with keys/addresses (for more effective retreival of
block chain)
- export/import/backup of wallet

Reported by andreas.schildbach on 2011-10-14 20:51:23

@mikehearn
Copy link
Member Author

Issue #370 is already high priority.  I was just wondering if there's something quick
we can do to improve the current serialization or if we should focus on #4.

Reported by miron@google.com on 2011-10-14 21:39:48

@mikehearn
Copy link
Member Author

Oh, it can be set to a megabyte and that should last a long time. Long chains of transactions
should be rare in normal usage.

Serialization sucks, I know. We'll get to it eventually.

Reported by hearn@google.com on 2011-10-15 16:22:17

@mikehearn
Copy link
Member Author

One user just hit this error at 108 incoming and 108 outgoing transactions with 96 kb
of stack.

Reported by andreas.schildbach on 2011-11-10 14:10:17

@mikehearn
Copy link
Member Author

Miron has implemented protobuf serialization for the wallet, which should resolve this
once users are upgraded.

Reported by hearn@google.com on 2012-01-11 18:54:36

  • Status changed: Fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Request for enhancement, or the implementation of one
Projects
None yet
Development

No branches or pull requests

1 participant