           # Reports this file's size
           o 'size0(Ljava/io/FileDescriptor;)J', (rs, _this, fd_obj) ->
             fd = fd_obj.get_field rs, 'Ljava/io/FileDescriptor;fd'
-            try
-              return gLong.fromNumber(fs.fstatSync(fd).size)
-            catch e
-              rs.java_throw rs.get_bs_class('Ljava/io/IOException;'), 'Bad file descriptor.'
+            rs.async_op (cb) ->
+              fs.fstat fd, (err, stats) ->
+                if err?
+                  rs.java_throw rs.get_bs_class('Ljava/io/IOException;'), 'Bad file descriptor.'
+                cb gLong.fromNumber(stats.size)
           o 'position0(Ljava/io/FileDescriptor;J)J', (rs, _this, fd, offset) ->
               parent = _this.get_field rs, 'Lsun/nio/ch/FileChannelImpl;parent'
               gLong.fromNumber(

              # this is a real file that we've already opened
              pos = _this.$pos
              buf = new Buffer n_bytes
              # if at end of file, return -1.
              filesize = fs.fstatSync(fd).size
              if filesize > 0 and pos >= filesize-1
                return -1
              bytes_read = fs.readSync(fd, buf, 0, n_bytes, pos)
              # not clear why, but sometimes node doesn't move the file pointer,
              # so we do it here ourselves
              _this.$pos += bytes_read
              byte_arr.array[offset+i] = buf.readUInt8(i) for i in [0...bytes_read] by 1
              return if bytes_read == 0 and n_bytes isnt 0 then -1 else bytes_read
            # reading from System.in, do it async
            rs.async_op (cb) ->
              rs.async_input n_bytes, (bytes) ->

            # read upto len bytes and store into mmap'd buffer at address
            block_addr = rs.block_addr(address)
            buf = new Buffer len
            rs.async_op (cb) ->
              fs.read fd, buf, 0, len, (err, bytes_read) ->
                if DataView?
                  for i in [0...bytes_read] by 1
                    rs.mem_blocks[block_addr].setInt8(i, buf.readInt8(i))
                else
                  for i in [0...bytes_read] by 1
                    rs.mem_blocks[block_addr+i] = buf.readInt8(i)
                cb bytes_read
          o 'preClose0(Ljava/io/FileDescriptor;)V', (rs, fd_obj) ->
            # NOP, I think the actual fs.close is called later. If not, NBD.
        ]
