portaldacalheta.pt
  • Principal
  • Investidores E Financiamento
  • Gerenciamento De Projetos
  • Noticias Do Mundo
  • Processo De Design
Tecnologia

Buscando vazamentos de memória Java



Programadores inexperientes costumam pensar que a coleta automática de lixo do Java os livra completamente de se preocupar com o gerenciamento de memória. Este é um equívoco comum: enquanto o coletor de lixo faz o seu melhor, é inteiramente possível que mesmo o melhor programador seja vítima de vazamentos de memória incapacitantes. Deixe-me explicar.

Um vazamento de memória ocorre quando as referências de objeto que não são mais necessárias são mantidas desnecessariamente. Esses vazamentos são ruim . Por um lado, eles colocam pressão desnecessária em sua máquina, pois seus programas consomem cada vez mais recursos. Para piorar as coisas, detectar esses vazamentos pode ser difícil: a análise estática muitas vezes se esforça para identificar com precisão essas referências redundantes, e as ferramentas de detecção de vazamentos existentes rastreiam e relatam informações refinadas sobre objetos individuais, produzindo resultados que são difíceis de interpretar e não têm precisão.



Em outras palavras, os vazamentos são muito difíceis de identificar ou identificados em termos muito específicos para serem úteis.



Na verdade, existem quatro categorias de problemas de memória com sintomas semelhantes e sobrepostos, mas com causas e soluções variadas:



  • atuação : geralmente associado à criação e exclusão excessiva de objetos, longos atrasos na coleta de lixo, troca excessiva de páginas do sistema operacional e muito mais.

  • Restrições de recursos : ocorre quando há pouca memória disponível ou sua memória está muito fragmentada para alocar um objeto grande - isso pode ser nativo ou, mais comumente, relacionado a heap Java.



  • Vazamentos de heap Java : o clássico vazamento de memória, no qual objetos Java são continuamente criados sem serem liberados. Isso geralmente é causado por referências de objetos latentes.

  • Vazamentos de memória nativa : associado a qualquer utilização de memória em crescimento contínuo que esteja fora do heap Java, como alocações feitas por código JNI, drivers ou até mesmo alocações JVM.



Neste tutorial de gerenciamento de memória, vou me concentrar em vazamentos de heap Java e delinear uma abordagem para detectar tais vazamentos com base em Java VisualVM relatórios e utilizando uma interface visual para analisar Java aplicativos baseados em tecnologia enquanto estão em execução.

Mas antes de evitar e localizar vazamentos de memória, você deve entender como e por que eles ocorrem. ( Nota: Se você tem um bom controle sobre as complexidades dos vazamentos de memória, você pode pular adiante . )



Vazamentos de memória: um manual

Para começar, pense no vazamento de memória como uma doença e OutOfMemoryError (OOM, para resumir) como um sintoma. Mas como acontece com qualquer doença, nem todos os OOMs implicam necessariamente vazamentos de memória : um OOM pode ocorrer devido à geração de um grande número de variáveis ​​locais ou outros eventos semelhantes. Por outro lado, nem todos os vazamentos de memória se manifestam necessariamente como OOMs , especialmente no caso de aplicativos de desktop ou aplicativos cliente (que não são executados por muito tempo sem reinicializações).

Pense no vazamento de memória como uma doença e no OutOfMemoryError como um sintoma. Mas nem todos os OutOfMemoryErrors implicam em vazamentos de memória, e nem todos os vazamentos de memória se manifestam como OutOfMemoryErrors.

Por que esses vazamentos são tão ruins? Entre outras coisas, o vazamento de blocos de memória durante a execução do programa muitas vezes degrada performance do sistema com o tempo, os blocos de memória alocados, mas não usados, terão que ser trocados assim que o sistema ficar sem memória física livre. Eventualmente, um programa pode até mesmo esgotar seu espaço de endereço virtual disponível, levando ao OOM.



Decifrando o OutOfMemoryError

Conforme mencionado acima, o OOM é uma indicação comum de vazamento de memória. Essencialmente, o erro é lançado quando não há espaço suficiente para alocar um novo objeto. Por mais que tente, o coletor de lixo não consegue encontrar o espaço necessário e o heap não pode ser expandido mais. Assim, surge um erro, juntamente com um rastreamento de pilha .

A primeira etapa para diagnosticar seu OOM é determinar o que o erro realmente significa. Isso parece óbvio, mas a resposta nem sempre é tão clara. Por exemplo: O OOM está aparecendo porque o heap Java está cheio ou porque o heap nativo está cheio? Para ajudá-lo a responder a essa pergunta, vamos analisar algumas das possíveis mensagens de erro:



  • java.lang.OutOfMemoryError: Java heap space

  • java.lang.OutOfMemoryError: PermGen space

  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit

  • java.lang.OutOfMemoryError: request bytes for . Out of swap space?

  • java.lang.OutOfMemoryError: (Native method)

“Java heap space”

Essa mensagem de erro não implica necessariamente em vazamento de memória. Na verdade, o problema pode ser tão simples quanto um problema de configuração.

Por exemplo, fui responsável por analisar um aplicativo que estava produzindo consistentemente esse tipo de OutOfMemoryError. Após alguma investigação, descobri que o culpado era uma instanciação de array que exigia muita memória; neste caso, não foi culpa do aplicativo, mas sim, o servidor do aplicativo estava contando com o tamanho de heap padrão, que era muito pequeno. Resolvi o problema ajustando o Parâmetros de memória JVM .

Em outros casos, e para aplicativos de longa duração em particular, a mensagem pode ser uma indicação de que não estamos intencionalmente segurando referências a objetos , evitando que o coletor de lixo os limpe. Esta é a linguagem Java equivalente a um vazamento de memória . ( Nota: APIs chamadas por um aplicativo também podem conter referências de objetos não intencionalmente. )

Outra fonte potencial desses OOMs de 'espaço de heap Java' surge com o uso de finalizadores . Se uma classe tiver um finalize , os objetos desse tipo não terão seu espaço recuperado no momento da coleta de lixo. Em vez disso, após a coleta de lixo, os objetos são enfileirados para finalização, o que ocorre posteriormente. Na implementação da Sun, os finalizadores são executados por um thread daemon . Se o encadeamento do finalizador não puder acompanhar a fila de finalização, o heap Java poderá ser preenchido e um OOM poderá ser lançado.

“Espaço PermGen”

Esta mensagem de erro indica que o geração permanente está cheio. A geração permanente é a área do heap que armazena objetos de classe e método. Se um aplicativo carregar um grande número de classes, o tamanho da geração permanente pode precisar ser aumentado usando -XX:MaxPermSize opção.

detecção de vazamento de memória node js

Internado java.lang.String os objetos também são armazenados na geração permanente. O java.lang.String classe mantém um pool de strings. Quando o método interno é invocado, o método verifica o pool para ver se uma string equivalente está presente. Em caso afirmativo, ele é retornado pelo método interno; caso contrário, a string é adicionada ao pool. Em termos mais precisos, o java.lang.String.intern método retorna uma string representação canônica ; o resultado é uma referência à mesma instância de classe que seria retornada se essa string aparecesse como um literal. Se um aplicativo estagiar um grande número de strings, pode ser necessário aumentar o tamanho da geração permanente.

Nota: você pode usar o jmap -permgen comando para imprimir estatísticas relacionadas à geração permanente, incluindo informações sobre instâncias de String internalizadas.

“O tamanho do array solicitado excede o limite da VM”

Este erro indica que o aplicativo (ou APIs usados ​​por esse aplicativo) tentou alocar uma matriz maior do que o tamanho do heap. Por exemplo, se um aplicativo tentar alocar uma matriz de 512 MB, mas o tamanho máximo de heap for 256 MB, um OOM será lançado com essa mensagem de erro. Na maioria dos casos, o problema é um problema de configuração ou um bug que ocorre quando um aplicativo tenta alocar um array massivo.

“Solicitar bytes para. Sem espaço de troca? ”

Esta mensagem parece ser um OOM. No entanto, o HotSpot VM lança essa exceção aparente quando uma alocação do heap nativo falha e o heap nativo pode estar próximo da exaustão. Incluídos na mensagem estão o tamanho (em bytes) da solicitação que falhou e o motivo da solicitação de memória. Na maioria dos casos, é o nome do módulo de origem que está relatando uma falha de alocação.

Se esse tipo de OOM for lançado, talvez seja necessário usar utilitários de solução de problemas em seu sistema operacional para diagnosticar o problema mais detalhadamente. Em alguns casos, o problema pode nem estar relacionado ao aplicativo. Por exemplo, você pode ver este erro se:

  • O sistema operacional está configurado com espaço de troca insuficiente.

  • Outro processo no sistema está consumindo todos os recursos de memória disponíveis.

Também é possível que o aplicativo tenha falhado devido a um vazamento nativo (por exemplo, se algum bit de aplicativo ou código de biblioteca está alocando memória continuamente, mas não consegue liberá-lo para o sistema operacional).

(Método nativo)

Se você vir essa mensagem de erro e o quadro superior do rastreamento de pilha for um método nativo, esse método nativo encontrou uma falha de alocação. A diferença entre esta mensagem e a anterior é que a falha de alocação de memória Java foi detectada em um JNI ou método nativo em vez de no código Java VM.

Se esse tipo de OOM for lançado, talvez seja necessário usar utilitários no sistema operacional para diagnosticar melhor o problema.

Falha de aplicativo sem OOM

Ocasionalmente, um aplicativo pode travar logo após uma falha de alocação do heap nativo. Isso ocorre se você estiver executando um código nativo que não verifica os erros retornados pelas funções de alocação de memória.

Por exemplo, o malloc a chamada do sistema retorna NULL se não houver memória disponível. Se o retorno de malloc não estiver marcada, o aplicativo pode travar ao tentar acessar um local de memória inválido. Dependendo das circunstâncias, esse tipo de problema pode ser difícil de localizar.

Em alguns casos, as informações do log de erros fatais ou do despejo de memória serão suficientes. Se a causa de uma falha for determinada como uma falta de tratamento de erros em algumas alocações de memória, você deverá descobrir o motivo da falha de alocação. Como acontece com qualquer outro problema de heap nativo, o sistema pode estar configurado com espaço de troca insuficiente, outro processo pode estar consumindo todos os recursos de memória disponíveis, etc.

Diagnosticando Vazamentos

Na maioria dos casos, o diagnóstico de vazamentos de memória requer um conhecimento muito detalhado do aplicativo em questão. Aviso: o processo pode ser demorado e iterativo.

Nossa estratégia para localizar vazamentos de memória será relativamente direta:

  1. Identifique os sintomas

  2. Ativar coleta de lixo detalhada

  3. Habilitar perfil

  4. Analise o traço

1. Identifique os sintomas

Conforme discutido, em muitos casos, o processo Java eventualmente lançará uma exceção de tempo de execução OOM, um indicador claro de que seus recursos de memória se esgotaram. Nesse caso, você precisa distinguir entre uma exaustão normal de memória e um vazamento. Analisar a mensagem do OOM e tentar encontrar o culpado com base nas discussões fornecidas acima.

Muitas vezes, se um aplicativo Java solicitar mais armazenamento do que o heap do tempo de execução oferece, pode ser devido a um design ruim. Por exemplo, se um aplicativo criar várias cópias de uma imagem ou carregar um arquivo em um array, ficará sem armazenamento quando a imagem ou o arquivo for muito grande. Este é um esgotamento normal de recursos. O aplicativo está funcionando conforme projetado (embora este design seja claramente estúpido).

Mas se um aplicativo aumentar constantemente sua utilização de memória enquanto processa o mesmo tipo de dados, você pode ter um vazamento de memória.

2. Habilite a coleta de lixo detalhada

Uma das maneiras mais rápidas de afirmar que você realmente tem um vazamento de memória é habilitar a coleta de lixo detalhada. Os problemas de restrição de memória geralmente podem ser identificados examinando os padrões no verbosegc resultado.

Especificamente, o -verbosegc O argumento permite gerar um rastreamento sempre que o processo de coleta de lixo (GC) for iniciado. Ou seja, conforme a memória é coletada como lixo, relatórios de resumo são impressos com erro padrão, dando a você uma noção de como sua memória está sendo gerenciada.

Aqui está uma saída típica gerada com –verbosegc opção:

saída detalhada da coleta de lixo

Cada bloco (ou estrofe) neste arquivo de rastreamento GC é numerado em ordem crescente. Para compreender esse rastreio, você deve examinar sucessivas estrofes de Falha de Alocação e procurar a memória liberada (bytes e porcentagem) diminuindo com o tempo enquanto a memória total (aqui, 19725304) está aumentando. Esses são sinais típicos de esgotamento da memória.

3. Ative a criação de perfil

Diferentes JVMs oferecem diferentes maneiras de gerar arquivos de rastreio para refletir a atividade de heap, que geralmente inclui informações detalhadas sobre o tipo e o tamanho dos objetos. Isso é chamado traçando o perfil da pilha .

4. Analise o traço

Este post foca no trace gerado pelo Java VisualVM. Os rastreamentos podem vir em formatos diferentes, pois podem ser gerados por diferentes ferramentas de detecção de vazamento de memória Java, mas a ideia por trás deles é sempre a mesma: encontre um bloco de objetos no heap que não deveria estar lá e determine se esses objetos se acumulam em vez de liberar. De particular interesse são os objetos temporários que são conhecidos por serem alocados toda vez que um determinado evento é disparado no aplicativo Java. A presença de muitas instâncias de objeto que deveriam existir apenas em pequenas quantidades geralmente indica um bug do aplicativo.

Por fim, a solução de vazamentos de memória requer que você analise seu código completamente. Aprender sobre o tipo de objeto que está vazando pode ser muito útil e acelerar consideravelmente a depuração.

Como a coleta de lixo funciona na JVM?

Antes de iniciarmos nossa análise de um aplicativo com um problema de vazamento de memória, vamos primeiro ver como a coleta de lixo funciona na JVM.

A JVM usa uma forma de coletor de lixo chamado de coletor de rastreamento , que opera essencialmente pausando o mundo ao seu redor, marcando todos os objetos raiz (objetos referenciados diretamente por threads em execução) e seguindo suas referências, marcando cada objeto que vê ao longo do caminho.

Java implementa algo chamado de geracional coletor de lixo com base no pressuposto da hipótese geracional, que afirma que a maioria dos objetos criados são rapidamente descartados , e objetos que não são coletados rapidamente podem ficar por aí por um tempo .

Com base nesta suposição, Objetos de partição Java em várias gerações . Aqui está uma interpretação visual:

Java divide em várias gerações

  • Geração jovem - É aqui que os objetos começam. Tem duas sub-gerações:

    • Espaço Eden - Os objetos começam aqui. A maioria dos objetos são criados e destruídos no Espaço Eden. Aqui, o GC faz GCs menores , que são coletas de lixo otimizadas. Quando um Minor GC é executado, todas as referências a objetos que ainda são necessários são migradas para um dos espaços sobreviventes (S0 ou S1).

    • Espaço Sobrevivente (S0 e S1) - Objetos que sobrevivem ao Eden acabam aqui. Existem dois deles, e apenas um está em uso a qualquer momento (a menos que haja um sério vazamento de memória). Um é designado como vazio , e o outro como viver , alternando com cada ciclo de GC.

  • Geração Tenured - Também conhecido como geração antiga (espaço antigo na Fig. 2), este espaço contém objetos mais antigos com vidas mais longas (movidos dos espaços dos sobreviventes, se viverem por tempo suficiente). Quando este espaço é preenchido, o GC faz um GC Completo , que custa mais em termos de desempenho. Se esse espaço crescer sem limite, a JVM lançará um OutOfMemoryError - Java heap space.

  • Geração Permanente - Uma terceira geração intimamente relacionada à geração tenured, a geração permanente é especial porque contém dados exigidos pela máquina virtual para descrever objetos que não têm uma equivalência no nível da linguagem Java. Por exemplo, objetos que descrevem classes e métodos são armazenados na geração permanente.

Java é inteligente o suficiente para aplicar diferentes métodos de coleta de lixo a cada geração. A geração jovem é tratada com um rastreamento, copiando coletor Chamou o Novo coletor paralelo . Esse colecionador para o mundo, mas como a geração jovem é geralmente pequena, a pausa é curta.

Para obter mais informações sobre as gerações JVM e como elas funcionam, visite o Gerenciamento de memória na máquina virtual Java HotSpot documentação.

Detectando um Vazamento de Memória

Para encontrar vazamentos de memória e eliminá-los, você precisa das ferramentas adequadas de vazamento de memória. É hora de detectar e remover esse vazamento usando o Java VisualVM .

Criação de Perfil Remotamente do Heap com Java VisualVM

VisualVM é uma ferramenta que fornece uma interface visual para visualizar informações detalhadas sobre os aplicativos baseados na tecnologia Java durante a execução.

onde aprender programação c

Com VisualVM, você pode visualizar dados relacionados a aplicativos locais e aqueles em execução em hosts remotos. Você também pode capturar dados sobre instâncias de software JVM e salvar os dados em seu sistema local.

Para se beneficiar de todos os recursos do Java VisualVM, você deve executar a plataforma Java, Standard Edition (Java SE) versão 6 ou superior.

Relacionado: Por que você já precisa atualizar para o Java 8

Habilitando conexão remota para o JVM

Em um ambiente de produção, muitas vezes é difícil acessar a máquina real na qual nosso código será executado. Felizmente, podemos criar o perfil de nosso aplicativo Java remotamente.

Primeiro, precisamos nos conceder acesso JVM na máquina de destino. Para fazer isso, crie um arquivo chamado jstatd.all.policy com o seguinte conteúdo:

grant codebase 'file:${java.home}/../lib/tools.jar' { permission java.security.AllPermission; };

Uma vez que o arquivo foi criado, precisamos habilitar conexões remotas para a VM de destino usando o jstatd - Daemon jstat de máquina virtual ferramenta, da seguinte forma:

jstatd -p -J-Djava.security.policy=

Por exemplo:

jstatd -p 1234 -J-Djava.security.policy=D:jstatd.all.policy

Com o jstatd iniciado na VM de destino, somos capazes de nos conectar à máquina de destino e criar o perfil do aplicativo remotamente com problemas de vazamento de memória.

Conectando a um Host Remoto

Na máquina cliente, abra um prompt e digite jvisualvm para abrir a ferramenta VisualVM.

Em seguida, devemos adicionar um host remoto no VisualVM. Como a JVM de destino está ativada para permitir conexões remotas de outra máquina com J2SE 6 ou superior, iniciamos a ferramenta Java VisualVM e nos conectamos ao host remoto. Se a conexão com o host remoto foi bem-sucedida, veremos os aplicativos Java que estão sendo executados na JVM de destino, como visto aqui:

executando no jvm alvo

Para executar um gerenciador de perfis de memória no aplicativo, basta clicar duas vezes em seu nome no painel lateral.

Agora que estamos todos configurados com um analisador de memória, vamos investigar um aplicativo com um problema de vazamento de memória, que chamaremos MemLeak .

MemLeak

Claro, existem várias maneiras de criar vazamentos de memória em Java. Para simplificar, definiremos uma classe como uma chave em um HashMap, mas não definiremos o equals () e hashcode () métodos.

Um HashMap é um mesa de hash implementação para a interface do Mapa e, como tal, define os conceitos básicos de chave e valor: cada valor está relacionado a uma chave única, portanto, se a chave para um determinado par de valor-chave já estiver presente no HashMap, seu valor atual será substituído.

É obrigatório que nossa classe principal forneça uma implementação correta de equals() e hashcode() métodos. Sem eles, não há garantia de que uma boa chave será gerada.

Por não definir o equals() e hashcode() , adicionamos a mesma chave ao HashMap repetidamente e, em vez de substituir a chave como deveria, o HashMap cresce continuamente, deixando de identificar essas chaves idênticas e lançando um OutOfMemoryError.

Esta é a classe MemLeak:

package com.post.memory.leak; import java.util.Map; public class MemLeak { public final String key; public MemLeak(String key) { this.key =key; } public static void main(String args[]) { try { Map map = System.getProperties(); for(;;) { map.put(new MemLeak('key'), 'value'); } } catch(Exception e) { e.printStackTrace(); } } }

Nota: o vazamento de memória é não devido ao loop infinito na linha 14: o loop infinito pode levar ao esgotamento de recursos, mas não a um vazamento de memória. Se tivéssemos implementado corretamente equals() e hashcode() métodos, o código funcionaria bem mesmo com o loop infinito, pois teríamos apenas um elemento dentro do HashMap.

(Para os interessados, Aqui são alguns meios alternativos de (intencionalmente) gerar vazamentos.)

Usando Java VisualVM

Com o Java VisualVM, podemos monitorar a memória do Java Heap e identificar se seu comportamento é indicativo de um vazamento de memória.

Aqui está uma representação gráfica do analisador Java Heap do MemLeak logo após a inicialização (lembre-se de nossa discussão sobre os vários gerações ):

monitorar vazamentos de memória usando java visualvm

Depois de apenas 30 segundos, a Old Generation está quase cheia, indicando que, mesmo com um Full GC, a Old Generation está sempre crescendo, um sinal claro de um vazamento de memória.

Um meio de detectar a causa deste vazamento é mostrado na imagem a seguir ( clique para ampliar ), gerado usando Java VisualVM com um heap dump . Aqui, vemos que 50% dos objetos Hashtable $ Entry estão no heap , enquanto a segunda linha nos aponta para o MemLeak classe. Assim, o vazamento de memória é causado por um mesa de hash usado dentro do MemLeak classe.

vazamento de memória da tabela de hash

Finalmente, observe o Java Heap logo após nosso OutOfMemoryError em que o As gerações jovens e velhas estão completamente cheias .

erro de falta de memória

Conclusão

Vazamentos de memória estão entre os aplicativos Java mais difíceis problemas para resolver , pois os sintomas são variados e difíceis de reproduzir. Aqui, descrevemos uma abordagem passo a passo para descobrir vazamentos de memória e identificar suas fontes. Mas, acima de tudo, leia as mensagens de erro com atenção e preste atenção aos rastreamentos de pilha - nem todos os vazamentos são tão simples quanto parecem.

Apêndice

Junto com o Java VisualVM, existem várias outras ferramentas que podem realizar a detecção de vazamento de memória. Muitos detectores de vazamento operam no nível da biblioteca, interceptando chamadas para rotinas de gerenciamento de memória. Por exemplo, HPROF, é uma ferramenta de linha de comando simples empacotada com o Java 2 Platform Standard Edition (J2SE) para heap e perfil de CPU. A saída de HPROF pode ser analisado diretamente ou usado como entrada para outras ferramentas como JHAT. Quando trabalhamos com aplicativos Java 2 Enterprise Edition (J2EE), há várias soluções de analisador de dump de heap que são mais amigáveis, como IBM Heapdumps para servidores de aplicativos Websphere .

Compreender o básico

O que é um vazamento de memória?

Um vazamento de memória ocorre quando a memória é marcada como 'em uso' mesmo que não seja mais necessária e nunca será liberada pelo processo que a criou.

Como você conserta um vazamento de memória?

Depende do vazamento em questão: alguns são mais simples de detectar e consertar do que outros. No final, tudo se resume a não reter referências a objetos que não são mais necessários. Às vezes, isso está em seu próprio código, mas às vezes está em bibliotecas que seu código usa.

Como você encontra um vazamento de memória?

Se um aplicativo aumentar constantemente sua utilização de memória enquanto processa o mesmo tipo de dados, pode haver um vazamento de memória. Você pode ajudar a estreitar as fontes de vazamento analisando vestígios. A presença de muitas instâncias de objetos que deveriam existir apenas em pequenas quantidades geralmente indica um vazamento de memória.

Qual é o tamanho do heap?

O tamanho do heap determina quanta memória está disponível para a JVM para alocação. Sempre que você cria um novo objeto, ele é armazenado no heap de forma contígua.

desempenho de node js vs python

Como funciona a coleta de lixo em Java?

A JVM usa diferentes métodos de coleta de lixo para diferentes grupos de dados. Os dados são classificados de acordo com o tempo que tendem a permanecer antes de serem descartados. Para dados de curto prazo, ele pausa tudo e usa um coletor de rastreamento e cópia para liberar memória que não é mais referenciada.

Como consertar vazamentos de memória em Java

Corrigir vazamentos de memória em Java envolve observar sintomas, usar GC detalhado e criar perfis e analisar rastreamentos de memória, seguido por uma revisão completa do código que faz uso dos objetos envolvidos no vazamento.

Criação de código verdadeiramente modular sem dependências

Gerenciamento De Projetos

Criação de código verdadeiramente modular sem dependências
Vasos virais: cinco navios que transportavam doenças

Vasos virais: cinco navios que transportavam doenças

Pesquisar

Publicações Populares
Violência explode em protesto contra o despejo do campo de Berlim
Violência explode em protesto contra o despejo do campo de Berlim
Introdução ao Docker: simplificando o DevOps
Introdução ao Docker: simplificando o DevOps
Ideia brilhante de Donald Trump: uma parede solar na fronteira EUA-México
Ideia brilhante de Donald Trump: uma parede solar na fronteira EUA-México
Uma visão geral completa das melhores ferramentas de visualização de dados
Uma visão geral completa das melhores ferramentas de visualização de dados
O valor do design thinking nos negócios
O valor do design thinking nos negócios
 
Introdução aos microsserviços: um tutorial do Dropwizard
Introdução aos microsserviços: um tutorial do Dropwizard
Com 21 anos e raízes de Kerala, é o mais jovem na lista de MBE do Queen
Com 21 anos e raízes de Kerala, é o mais jovem na lista de MBE do Queen
Um bebê pode ouvir sons no útero?
Um bebê pode ouvir sons no útero?
Os desafios da aprendizagem remota para crianças pequenas
Os desafios da aprendizagem remota para crianças pequenas
ASSISTIR: A sessão de fotos do casamento de noivas captura o momento em que a explosão rasgou a cidade de Beirute
ASSISTIR: A sessão de fotos do casamento de noivas captura o momento em que a explosão rasgou a cidade de Beirute
Publicações Populares
  • explicar a teoria da gestalt e citar um exemplo
  • dotnet social cloudapp net redirecion
  • s-corporation vs c-corporation
  • ênfase em princípios de design
  • construindo um blog com angularjs
  • declarar uma classe em python
Categorias
  • Investidores E Financiamento
  • Gerenciamento De Projetos
  • Noticias Do Mundo
  • Processo De Design
  • © 2022 | Todos Os Direitos Reservados

    portaldacalheta.pt