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

В моем приложении 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

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

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

Спасибо.

Замените это: payload = Files.readAllBytes(Paths.get(files[i].toURI())); gateway.upload(payload, files[i].getName(), path); На это: Path tempFile = Paths.get(files[i].toURI()); gateway.upload(tempFile.toFile());

Raphael 21.11.2018 14:34

Вам нужно работать с InputStream вместо массива или всего большого двоичного объекта, который будет находиться в памяти. Это может быть ByteArrayInputStream, FileInputStream и т. д. Изучите документацию java для sftp-адаптера, чтобы узнать, какие интерфейсы доступны.

Raphael 21.11.2018 14:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
1 900
0

Другие вопросы по теме