AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77030026
Accepted
davidalayachew
davidalayachew
Asked: 2023-09-03 04:56:29 +0800 CST2023-09-03 04:56:29 +0800 CST 2023-09-03 04:56:29 +0800 CST

ModuleLayer não consegue encontrar meus recursos ao executar meu programa modular, mas pode encontrar meu jar modular

  • 772

Eu tenho a seguinte estrutura de projeto.

ProjectName
|
|---src
    |
    |---main
        |
        |---java
        |   |
        |   |---ModuleName
        |       |
        |       |---module-info.java
        |       |
        |       |---PackageName
        |           |
        |           |---Main.java
        |
        |---resources
            |
            |---ResourceParentFolder
                |
                |---ResourceSubFolderA
                |   |
                |   |---Resource1A.png
                |   |---Resource2A.png
                |   |---Resource3A.png
                |
                |---ResourceSubFolderB
                    |
                    |---Resource1B.png
                    |---Resource2B.png
                    |---Resource3B.png

Eu tenho um script de shell que compila o código e depois o executa.

javac                                        \
        --module-source-path="src/main/java" \
        --module=ModuleName                  \
        -d classes

java                                               \
        --module-path="classes;src/main/resources" \
        --module=ModuleName/PackageName.Main

Também tenho um script de shell que transforma meu código compilado em um jar modular e, em seguida, executa esse jar.

jar                                               \
        --verbose                                 \
        --create                                  \
        --file run/executable/jar/ProjectName.jar \
        --main-class PackageName.Main             \
        -C classes/ModuleName .                   \
        -C src/main/resources .

java                                         \
        --module-path="run/executable/jar"   \
        --module=ModuleName/PackageName.Main

No meu método principal, tenho uma chamada para java.lang.module.ModuleReader, especificamente para o método list() , que me permite percorrer meu módulo e seu conteúdo.

Consigo ver o conteúdo do meu ResourceParentFolderse pegar meu arquivo jar e tentar executá-lo, mas a chamada para list()retorna os .classarquivos apenas quando estou executando apenas meu código compilado. Isso ocorre porque meu módulo está configurado incorretamente? Ou isso é simplesmente uma funcionalidade não suportada?

Novamente, ModuleReader.list()retorna uma lista recursiva do conteúdo do meu código-fonte e da minha pasta de recursos quando executado como um jar, mas só retorna o código-fonte quando executado como código compilado. Como faço para que o código compilado também preencha o ModuleReader.list()? Ou essa funcionalidade simplesmente não é suportada, a menos que esteja em uma jarra ou algo assim?

E para ser claro, estou bem ciente de que existem um milhão e mais uma maneira de obter um recurso. Mas quero saber se é possível fazer do jeito que solicitei acima. E se não, então por quê?

EDIT - detalhando algumas das minhas tentativas fracassadas.

Tentei copiar o src/main/resourcesdiretório para classeso local do meu módulo antes que ele se transformasse em um jar. Infelizmente, nada foi captado por ele.

Também tentei fazer --patch-modules, mas também falhou, mas com erro.

error: no source files

Aqui está o comando que usei.

javac   --patch-module ModuleName=src/main/resources
java
  • 1 1 respostas
  • 34 Views

1 respostas

  • Voted
  1. Best Answer
    Slaw
    2023-09-03T06:55:49+08:002023-09-03T06:55:49+08:00

    Sua tentativa de adicionar src/main/resourcesao caminho do módulo não funcionará conforme o esperado. Simplesmente adicionar diretórios ao caminho do módulo não torna o conteúdo deles parte do seu módulo. Você precisa:

    1. Tenha as classes e os recursos no mesmo local, seja um diretório ou um arquivo JAR. Isso torna os recursos parte do módulo. E observe que é por isso que seu arquivo JAR funciona conforme o esperado, porque você empacotou as classes e os recursos no mesmo arquivo JAR.

      Essa abordagem é essencialmente como "deveria ser feita".

    2. Use --patch-moduleem tempo de execução. Observe que esta abordagem não requer a movimentação dos arquivos de recursos para qualquer lugar.

      Além disso, você usaria esse argumento em tempo de compilação se estivesse tentando opensum pacote somente de recursos; caso contrário, será emitido um aviso informando que o pacote não existe. Embora, se bem me lembro, você receberá um erro em tempo de execução neste cenário (onde um opens pacote não é inerentemente parte do módulo), mesmo com um --patch-moduleargumento.

    Dito isso, recomendo usar uma ferramenta de construção (por exemplo, Maven, Gradle, etc.) para projetos Java não triviais. Eles normalmente cuidarão de tudo isso para você.


    Exemplo

    Aqui está um exemplo de ambas as abordagens discutidas acima. Observe que todos os comandos foram executados no diretório do projeto no Windows 10 usando PowerShell Core 7.2.13 e Java 20.0.1.

    Embora a saída abaixo liste diretórios de recursos , bem como recursos reais, isso não é garantido. Na verdade, se não me engano, esses mesmos diretórios não serão listados quando o módulo for empacotado em uma imagem de tempo de execução (via / jlink) jpackage.

    Código fonte

    O código-fonte é o mesmo em ambas as abordagens.

    informações do módulo

    module app {}
    

    amostra.Principal

    package sample;
    
    public class Main {
    
        public static void main(String[] args) throws Exception {
            var module = Main.class.getModule();
            var reference = module.getLayer()     // ModuleLayer
                    .configuration()              // Configuration
                    .findModule(module.getName()) // Optional<ResolvedModule>
                    .orElseThrow()                // ResolvedModule
                    .reference();                 // ModuleReference
            try (var reader = reference.open()) {
                reader.list().forEach(System.out::println);
            }
        }
    }
    

    Estrutura de diretório

    <PROJECT-DIR>
    |
    \---src
        \---main
            +---java
            |   \---app
            |       |   module-info.java
            |       |
            |       \---sample
            |               Main.java
            |
            \---resources
                \---app
                    \---foo
                            res.txt
    

    Observe que adicionei um app"diretório de módulo" src/main/resourcessimplesmente para espelhar o que foi feito src/main/java(o que é necessário se você quiser usar --module-source-pathe --modulecom javac). Isso não é necessário, embora não fosse necessário alterar ligeiramente os comandos usados ​​​​abaixo (apenas alterações nos caminhos).

    Abordagem 1 – Mesclar Classes e Recursos

    Comandos

    & javac --module-source-path src\main\java --module app -d build\classes
    & robocopy src\main\resources build\classes /S > NUL
    & java --module-path build\classes --module app/sample.Main
    

    Saída

    foo/
    foo/res.txt      
    module-info.class
    sample/
    sample/Main.class
    

    Como você pode ver, o recurso foo/res.txt(e até mesmo o diretório foo/) foi listado.

    Estrutura de diretório (após executar comandos)

    <PROJECT-DIR>
    |
    +---build
    |   \---classes
    |       \---app
    |           |   module-info.class   
    |           |
    |           +---foo
    |           |       res.txt
    |           |
    |           \---sample
    |                   Main.class      
    |
    \---src
        \---main
            +---java
            |   \---app
            |       |   module-info.java
            |       |
            |       \---sample
            |               Main.java   
            |
            \---resources
                \---app
                    \---foo
                            res.txt 
    

    Abordagem 2 - Uso--patch-module

    Comandos

    & javac --module-source-path src\main\java --module app -d build\classes
    & java --module-path build\classes --patch-module app=src\main\resources\app --module app/sample.Main
    

    Saída

    module-info.class
    sample/
    sample/Main.class
    foo/
    foo/res.txt
    

    Novamente, você pode ver que o recurso foo/res.txt(e o diretório foo/) foi listado.

    Estrutura de diretório (após executar comandos)

    <PROJECT-DIR>
    |
    +---build
    |   \---classes
    |       \---app
    |           |   module-info.class
    |           |
    |           \---sample
    |                   Main.class
    |
    \---src
        \---main
            +---java
            |   \---app
            |       |   module-info.java
            |       |
            |       \---sample
            |               Main.java
            |
            \---resources
                \---app
                    \---foo
                            res.txt
    
    • 2

relate perguntas

  • Lock Condition.notify está lançando java.lang.IllegalMonitorStateException

  • Resposta de microsserviço Muitos para Um não aparece no carteiro

  • Validação personalizada do SpringBoot Bean

  • Os soquetes Java são FIFO?

  • Por que não é possível / desencorajado definir um lado do servidor de tempo limite de solicitação?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve