# Jenetics: a genetic algorithm library for Java that runs evolution as a Stream

> Jenetics is an Apache-2.0 Java library for genetic algorithms, genetic programming, grammatical evolution and multi-objective optimization. It requires Java 25, and its defining design choice is that evolution runs as an EvolutionStream rather than a loop you write yourself.

**jenetics/jenetics** — Jenetics - Genetic Algorithm, Genetic Programming, Grammatical Evolution, Evolutionary Algorithm, and Multi-objective Optimization

- Repository: https://github.com/jenetics/jenetics
- Website: https://jenetics.io
- Stars: 909 · Forks: 161
- Language: Java
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/jenetics-jenetics

## What Jenetics solves, and who is meant to use it

Jenetics is a Java library for search and optimization problems where you can score a candidate solution but cannot easily derive one. The README lists the covered techniques plainly: genetic algorithm, evolutionary algorithm, grammatical evolution, genetic programming, and multi-objective optimization. The intended user is a Java developer who already has a fitness function in mind and needs the surrounding machinery (population, selection, crossover, mutation) without implementing it.

The README is explicit that the library "allows you to minimize and maximize the given fitness function without tweaking it." That is a smaller claim than it sounds. It means the Engine does not force you to negate your objective or normalize it, which is a common source of sign errors in hand-written evolutionary code. The library is not a machine-learning framework in the scikit-learn sense: there is no dataset abstraction, no train/test split, no model persistence format for learned parameters. It optimizes a function you supply.

Who it is not for: anyone who wants a drop-in solver. The README's own framing puts the burden on the user at step one, describing the transformation of the problem domain into a Genotype representation as "the probably most challenging part" of setting up an Engine. If you cannot express your problem as a fixed or variable-length sequence of genes, Jenetics gives you nothing to start from.

## The EvolutionStream and the Genotype-to-Phenotype pipeline

The architecture separates the concepts the README names: Gene, Chromosome, Genotype, Phenotype, Population, and the fitness Function. A Gene is the smallest unit. A Chromosome is a sequence of genes of one type, such as BitChromosome or a numeric chromosome. A Genotype bundles one to n chromosomes, and it also implements the Factory interface, so the same object that describes the search space also generates the initial random population.

The distinguishing mechanism is the EvolutionStream. Other GA implementations typically expose a run loop or an evolve call that returns a final population. Jenetics instead returns a stream, and because EvolutionStream implements the Java Stream interface, the README states that it "works smoothly with the rest of the Java Stream API." In practice this means generation count, convergence criteria and result extraction are expressed as stream operations: limit, takeWhile, collect. A termination condition is a predicate on an EvolutionResult, not a field in a configuration object.

That choice has a real consequence. Because the stream is lazy, nothing evolves until a terminal operation is attached. It also means a partially consumed stream is a partially run evolution, which is convenient for inspection and awkward if you expected the engine to own its own lifecycle. The Engine itself is built through Engine.builder(fitness, genotypeFactory), and the builder is where alterers, population size and other operators get attached. The README does not document rollback or checkpointing of a running evolution in the excerpt available.

## Installing Jenetics and running a first evolution

Jenetics requires at least Java 25 to compile and run. The README links to Maven Central under the io.jenetics group, so a build-tool dependency is the normal route. The repository itself is a multi-module Gradle build; the README instructs you to clone it and notes that ./gradlew jar compiles the sources and writes JARs into each module's build/libs directory. Building from source is only necessary if you want to modify the library, and the README gives the clone and build commands directly:

```bash
$ git clone https://github.com/jenetics/jenetics.git <builddir>
$ cd <build-dir>
$ ./gradlew jar
```

The README's Hello World example is a ones-counting problem. It defines a genotype factory holding a single BitChromosome, then a fitness function that reads the chromosome back as a BitChromosome and counts its set bits. The Engine is constructed from the method reference and the factory, and the result is pulled out of the stream:

```java
Factory<Genotype<BitGene>> gtf =
    Genotype.of(BitChromosome.of(10, 0.5));

Engine<BitGene, Integer> engine = Engine
    .builder(HelloWorld::eval, gtf)
    .build();

Genotype<BitGene> result = engine.stream()
    .limit(100)
    .collect(EvolutionResult.toBestGenotype());
```

Running this prints the genotype with the most set bits found across 100 generations. The two arguments to BitChromosome.of are the chromosome length and the gene probability, so 10 and 0.5 give a ten-bit chromosome initialized with a fair coin. Note that the example uses IO.println, which matches the Java 25 baseline rather than the older System.out.println idiom. If your build fails on this line, your toolchain is older than the library's stated requirement.

## Where Jenetics gets in the way: encoding, Java 25, and no built-in stopping rule

The first limitation is the Java 25 floor. The README states the requirement without qualification, and the example code uses APIs consistent with it. Projects pinned to Java 17 or 21 cannot use this release without either upgrading or staying on an older Jenetics line, and the README does not describe a compatibility mode or a backport.

The second limitation is encoding. Jenetics does not help you decide how to represent a solution. If your problem is a permutation with hard constraints, a variable-length program, or a continuous function with boundaries, you are choosing and configuring chromosomes and alterers yourself. The README points to jenetics.ext for multi-objective problems and grammatical evolution, and to jenetics.prog for genetic programming, which tells you the core module alone will not cover those cases.

The third is that the stream model gives you no default termination. The Hello World example uses limit(100), a fixed generation count. There is no documented convergence detector in the excerpt; if you stop at a fixed count you may stop early on an easy problem or waste generations on a hard one. The README does not document rollback of a partially completed evolution, so a long run interrupted mid-stream has no documented recovery path. Treat long runs as something you manage at the application level, not something the library manages for you.

## Jenetics compared with a Python-first evolutionary framework

The closest thing to a direct alternative in the README is not a competing Java library but the ecosystem difference. Jenetics is a Java library that plugs into the JVM build and runtime you already have. A Python-first framework such as DEAP occupies the opposite position: it lives in the scientific Python stack, integrates with NumPy-style array work, and is typically driven from a notebook or a script rather than compiled into a service.

The practical difference is not raw capability, since both implement selection, crossover and mutation. It is where the fitness function lives. If your fitness function calls into a Java service, a JVM-based simulator, or a large existing Java codebase, Jenetics removes a serialization boundary that a Python framework would introduce. If your fitness function is a numerical model written in Python, Jenetics would force you to reimplement or bridge it, and the bridge would dominate the runtime.

Jenetics also carries a design difference worth naming: the stream-based execution model. A framework that exposes a run loop makes it natural to inspect intermediate populations by mutating shared state. Jenetics pushes you toward functional composition of stream stages instead. That is cleaner for reproducibility and more awkward if you want to pause, persist and resume an evolution, which the documentation does not describe.

## Licence, module layout and the cost of upgrading

Jenetics is licensed under Apache-2.0, and the repository carries both LICENSE.txt and NOTICE.txt at the top level. Apache-2.0 permits commercial use and modification and includes an explicit patent grant, with the usual obligations around preserving notices. This is a permissive licence, not a copyleft one, so linking it into a closed-source product is consistent with the licence terms. That is a statement about the licence text, not legal advice; your own counsel should confirm obligations for your distribution model.

The module split affects both your dependency list and your upgrade surface. The core jenetics artifact is separate from jenetics.ext, jenetics.prog and jenetics.xml. If you only use the core, an upgrade in the extension modules does not touch you. If you use grammatical evolution or multi-objective optimization, you depend on jenetics.ext and inherit its release cadence. The repository also contains non-published modules such as jenetics.distassert, jenetics.example and jenetics.tool, which are not Maven artifacts and are not part of your dependency graph.

The maintenance picture from the repository metadata: the last push to master was on 2026-09-09, and the most recent release is v9.1.0 from 2026-09-02. The project is not archived. Upgrading across the 9.x line is the realistic path; the jump from 8.3.0 to 9.0.0 is where the Java 25 requirement appears, so that is the boundary to check if you are currently on 8.x.

## Conclusion

Adopt Jenetics when your problem is already expressed in Java and you want a genotype, a fitness function and a stream of generations without writing selection or mutation code. Do not adopt it if you are locked to a Java version below 25, or if your problem has no natural fixed-length encoding, since the README itself calls building the Genotype factory the most challenging part of setting up an Engine. Before committing, verify three things: that your toolchain can build against Java 25, that the module you need (jenetics.ext for multi-objective and grammatical evolution, jenetics.prog for genetic programming) is published to Maven Central under the io.jenetics group, and that the 9.1 manual covers the operator you intend to configure. The library is a toolkit, not a solver, so the quality of your encoding decides the outcome.

## FAQ

### What is Jenetics?

Jenetics is a Java library for genetic algorithms, evolutionary algorithms, grammatical evolution, genetic programming and multi-objective optimization. It is licensed under Apache-2.0 and requires at least Java 25 to compile and run.

### What is a genetic algorithm used for?

In Jenetics terms, it is used to minimize or maximize a fitness function you supply, without tweaking that function for direction. The README's Hello World example uses it to find the bit chromosome with the most set bits.

### How do I install Jenetics in a Java project?

Add the io.jenetics:jenetics artifact from Maven Central as a dependency, or clone the repository and run ./gradlew jar to build the JARs into each module's build/libs directory. Building from source requires Java 25.

### Which Jenetics module do I need for genetic programming or multi-objective optimization?

The README assigns multi-objective problems and grammatical evolution to jenetics.ext, and genetic programming to jenetics.prog. The core jenetics module contains the base data structures and the Engine.

### Why does the Jenetics example use IO.println instead of System.out.println?

The README's Hello World listing calls IO.println, which is consistent with the library's stated Java 25 baseline. If that line does not compile, your toolchain predates the requirement.

## Sources

- [jenetics/jenetics on GitHub](https://github.com/jenetics/jenetics)
- [License: Apache-2.0](https://github.com/jenetics/jenetics/blob/master/LICENSE)
- [Project website](https://jenetics.io)
- [README](https://github.com/jenetics/jenetics/blob/master/README.md)
- [Releases](https://github.com/jenetics/jenetics/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jenetics-jenetics
