<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m" -->

---
title: Security Baked Into the JVM: DirtyChai scales...
description: DirtyChai and JGDMS make Java's old SecurityManager model practical under load by removing locks and caches that used to block every check. DirtyChai scales...
canonical: https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Security Baked Into the JVM: DirtyChai scales vertically, JGDMS scales horizontally | daily.dev
og:description: DirtyChai and JGDMS make Java's old SecurityManager model practical under load by removing locks and caches that used to block every check. DirtyChai scales...
og:url: https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m
og:image: https://api.daily.dev/og/posts/ZyInVYl8M.png
og:image:alt: Security Baked Into the JVM: DirtyChai scales vertically, JGDMS scales horizontally
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Baked Into the JVM: DirtyChai scales vertically, JGDMS scales horizontally

**[A Java geek](https://daily.dev/sources/frankel)** · 9 min read · 0 upvotes · 0 comments

## Summary

DirtyChai and JGDMS make Java's old SecurityManager model practical under load by removing locks and caches that used to block every check. DirtyChai scales inside a single JVM: each virtual thread runs under the immutable context of its creator, and a DomainIdentity class gives ProtectionDomains value equality so contexts can be cached and reused. Its ConcurrentPolicyFile drops locking and caching entirely, since grants never mutate, and measured permission checks cost about 1.9 microseconds on a platform thread and 4.7 microseconds on a virtual thread. JGDMS scales horizontally: engines are stateless, verdicts are content-addressed by SHA-256 hash, and leases let crashed services clean themselves out of the registry automatically.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://blog.frankel.ch/security-baked-into-jvm/6>

## Questions this post answers

### How much does a permission check cost on a virtual thread compared to a platform thread in DirtyChai's security model?

A permission check under a least-privilege policy with no AllPermission costs about 1.9 microseconds on a platform thread and about 4.7 microseconds on a virtual thread. The actual share of a request this represents depends on what the request does. This is achieved by removing locks and caches from the policy evaluation path entirely, since grants are published once and never mutated.

_Developers tuning JVM security overhead can track benchmarks like this one on daily.dev._

### Why do virtual threads have no permissions when a SecurityManager is set in Java?

JEP 444 states that virtual threads have no permissions when running with a SecurityManager set, which is the default behavior on stock OpenJDK up to version 23; from OpenJDK 24 onward there is no SecurityManager to set at all. DirtyChai addresses this gap by building each virtual thread with the security context of the thread that created it, rather than an empty inherited context.

_Teams relying on SecurityManager-based access control can follow JVM changes like this on daily.dev before upgrading._

### How does ProtectionDomain equality affect AccessControlContext caching performance?

ProtectionDomain normally compares by object identity, so two domains describing identical code, permissions, and principals count as different objects and defeat caching. DirtyChai's DomainIdentity subclass computes equals and hashCode from code source, permissions, class loader, and principals instead, so a recombined context becomes equal to a previous one and the AccessControlContext cache can hand back the cached instance rather than rebuilding it.

_Engineers debugging JVM security cache misses can dig into cases like this on daily.dev._

## Similar posts on daily.dev

- [Security Baked Into the JVM: why fork Apache River and OpenJDK?](https://daily.dev/posts/security-baked-into-the-jvm-why-fork-apache-river-and-openjdk--jddvz9ame) · A Java geek · 1 upvotes · 0 comments
- [Security Baked Into the JVM: sixteen Subjects on the wire](https://daily.dev/posts/security-baked-into-the-jvm-sixteen-subjects-on-the-wire-uzxglis4o) · A Java geek · 2 upvotes · 1 comments
- [Security Baked Into the JVM: no single party controls the outcome](https://daily.dev/posts/security-baked-into-the-jvm-no-single-party-controls-the-outcome-8thqti56v) · A Java geek · 0 upvotes · 0 comments
- [Security Baked Into the JVM: two Subjects, one call](https://daily.dev/posts/security-baked-into-the-jvm-two-subjects-one-call-fifkkyz8a) · A Java geek · 2 upvotes · 2 comments

---

Tags: [#java](https://daily.dev/tags/java), [#distributed-systems](https://daily.dev/tags/distributed-systems)

[View this post on daily.dev](https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Security Baked Into the JVM: DirtyChai scales vertically, JGDMS scales horizontally","url":"https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m"},"datePublished":"2026-10-25T17:23:27.227Z","dateModified":"2026-10-25T17:24:01.994Z","description":"DirtyChai and JGDMS make Java's old SecurityManager model practical under load by removing locks and caches that used to block every check. DirtyChai scales...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/c8cd71ebe6fdc59f92fd51949e181779?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/c8cd71ebe6fdc59f92fd51949e181779?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"A Java geek","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"A Java geek","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/b7f3fdbf443347ea84705578a195085b","url":"https://daily.dev/sources/frankel"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"java,distributed-systems","timeRequired":"PT9M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"A Java geek","item":"https://daily.dev/sources/frankel"},{"@type":"ListItem","position":3,"name":"Security Baked Into the JVM: DirtyChai scales vertically, JGDMS scales horizontally"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/security-baked-into-the-jvm-dirtychai-scales-vertically-jgdms-scales-horizontally-zyinvyl8m#faq","mainEntity":[{"@type":"Question","name":"How much does a permission check cost on a virtual thread compared to a platform thread in DirtyChai's security model?","acceptedAnswer":{"@type":"Answer","text":"A permission check under a least-privilege policy with no AllPermission costs about 1.9 microseconds on a platform thread and about 4.7 microseconds on a virtual thread. The actual share of a request this represents depends on what the request does. This is achieved by removing locks and caches from the policy evaluation path entirely, since grants are published once and never mutated. Developers tuning JVM security overhead can track benchmarks like this one on daily.dev."}},{"@type":"Question","name":"Why do virtual threads have no permissions when a SecurityManager is set in Java?","acceptedAnswer":{"@type":"Answer","text":"JEP 444 states that virtual threads have no permissions when running with a SecurityManager set, which is the default behavior on stock OpenJDK up to version 23; from OpenJDK 24 onward there is no SecurityManager to set at all. DirtyChai addresses this gap by building each virtual thread with the security context of the thread that created it, rather than an empty inherited context. Teams relying on SecurityManager-based access control can follow JVM changes like this on daily.dev before upgrading."}},{"@type":"Question","name":"How does ProtectionDomain equality affect AccessControlContext caching performance?","acceptedAnswer":{"@type":"Answer","text":"ProtectionDomain normally compares by object identity, so two domains describing identical code, permissions, and principals count as different objects and defeat caching. DirtyChai's DomainIdentity subclass computes equals and hashCode from code source, permissions, class loader, and principals instead, so a recombined context becomes equal to a previous one and the AccessControlContext cache can hand back the cached instance rather than rebuilding it. Engineers debugging JVM security cache misses can dig into cases like this on daily.dev."}}]}
```

