Spring-Integration, выгрузка файла на удаленный SFTP-сервер - java.lang.OutOfMemoryError: прямая буферная память - PullRequest
0 голосов
/ 21 ноября 2018

В моем приложении SpringBoot я использовал Spring Integration для загрузки файлов на удаленный SFTP-сервер.
Ниже приведен фрагмент кода, который я использовал для передачи файла на SFTP-сервер.

protected String transfer(String downloadDirectory) {
        File[] files = new File(downloadDirectory).listFiles();
        byte[] payload = null;
        String path = null;
        try {

            path = getSftpPath(downloadDirectory);
            for (int i = 0; i < files.length; i++) {
                if (files[i].isFile()) {
                    payload = Files.readAllBytes(Paths.get(files[i].toURI()));
                    gateway.upload(payload, files[i].getName(), path);
                }
            }
        } catch (Exception e) {

            throw new Exception(e);
        }
        return path;
    }

Объявление метода загрузки и MessageHandler выглядит следующим образом:

@MessagingGateway(asyncExecutor = "sftpAsync")
    public interface UploadGateway {
        @Gateway(requestChannel = "toSftpChannel")
        void upload(@Payload byte[] file, @Header("filename") String filename, @Header("path") String path);
    }

 @Bean
    @ServiceActivator(inputChannel = "toSftpChannel")
    public MessageHandler handler() {
        SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
        ExpressionParser expressionParser = new SpelExpressionParser();
        handler.setRemoteDirectoryExpression(expressionParser.parseExpression("headers['path']"));
        handler.setFileNameGenerator(msg -> (String) msg.getHeaders().get("filename"));
        handler.setAutoCreateDirectory(true);
        return handler;
    }

Отлично работает для загрузки файлов на удаленный SFTP-сервер.Но после пары выполнений он начинает показывать

java.lang.OutOfMemoryError: Direct buffer memory
    at java.nio.Bits.reserveMemory(Unknown Source)
    at java.nio.DirectByteBuffer.<init>(Unknown Source)
    at java.nio.ByteBuffer.allocateDirect(Unknown Source)
    at sun.nio.ch.Util.getTemporaryDirectBuffer(Unknown Source)
    at sun.nio.ch.IOUtil.read(Unknown Source)
    at sun.nio.ch.FileChannelImpl.read(Unknown Source)
    at sun.nio.ch.ChannelInputStream.read(Unknown Source)
    at sun.nio.ch.ChannelInputStream.read(Unknown Source)
    at sun.nio.ch.ChannelInputStream.read(Unknown Source)
    at java.nio.file.Files.read(Unknown Source)
    at java.nio.file.Files.readAllBytes(Unknown Source)

payload = Files.readAllBytes(Paths.get(files[i].toURI())); - это строка, в которую выдается указанное выше сообщение об ошибке.

Насколько я понимаю, я читаю весь файл в байтмассив, следовательно, я получаю эту ошибку.Поскольку мне нужен весь файл для отправки в метод загрузки, я следовал подходу byte [].

Я уже проверил ниже упомянутые темы.

Byte [] и java.lang.OutOfMemoryErrorчтение файла по битам

java.lang.OutOfMemoryError: прямая буферная память при вызове Files.readAllBytes

, но для метода загрузки требуется весь файл вместо потокабайты или порции данных (поправьте меня, если я ошибаюсь).

Так что любые предложения, чтобы избежать вышеупомянутой проблемы, очень помогают.

Спасибо.

...