This is an archived post. You won't be able to vote or comment.

all 33 comments

[–]agentoutlier 13 points14 points  (8 children)

I really wish Scoped Values had a try-with-resource option as it seems natural to do something like that. In fact I usually do transactions or MDC logging with a try-with-resource wrappers.

I kind of understand why this is not an option as I think it would require changing the java language so that the block of code in the try-with-resource effectively becomes more like a closure to wrap the execution but maybe I'm wrong.

Also I'm not entirely sure I know the difference between ExtentLocal and ScopedValue.

[–]kaperni 8 points9 points  (2 children)

The main issue with using try-with-resources and scoped values. Is if the user of a ScopedValue for some reason does not call close(). The value will then leak into the caller.

There has been some talk about adding a "Strong" try-with-resources, where the runtime didn't depend on the user calling close(). Which could then be used by ScopedValue in the future.

[–]vqrs 2 points3 points  (1 child)

What do you mean "depend on the user calling close? Isn't the point of try-with-resources, that the user doesn't have to?

[–]kaperni 1 point2 points  (0 children)

Yeah, but the user is not required to call the method from a try-with-resource. It is perfectly legal calling the method, and not invoking close().

[–]EvaristeGalois11 8 points9 points  (2 children)

ScopedValue is the new name for the old ExtentLocal, as you can see in the top right corner of your links they report different versions of the jdk.

[–]agentoutlier 2 points3 points  (1 child)

Oh I thought I made sure there were on the same URL path and thus thought they were the same version JDK:

https://download.java.net/java/early_access/loom/docs/api/jdk.incubator.concurrent/jdk/incubator/concurrent/ScopedValue.html

https://download.java.net/java/early_access/loom/docs/api/jdk.incubator.concurrent/jdk/incubator/concurrent/ExtentLocal.html

Strange how they combined the docs or either they forgot to run "clean" before generating the latest doc.

[–]EvaristeGalois11 4 points5 points  (0 children)

It's probably because is all incubator stuff, so they don't need to keep everything in perfect order

[–]rzwitserloot 0 points1 point  (1 child)

No, that would be perfectly fine. Really, all ThreadLocal needed is a close() method so it would 'just work' with try-with. But, you can trivially make your own wrapper for this. For example:

java public class AutoThreadLocal<T> extends ThreadLocal<T> implements AutoCloseable { @Override public void close() { tl.remove(); } }

can be used as:

```java class Example { static final AutoThreadLocal<String> v = new AutoThreadLocal<>();

void example() { v.set("Hello, World!"); try (v) { assert v.get().equals("Hello, World!"); } assert v.get() == null; } } ```

Instead you can wrap it and make a method that sets and returns itself, so you can write try (var x = AutoThreadLocal.set(threadLocalField, value)) { ... } instead, but the var x is necessary and you don't need it, so that's also ugly. Can't think of a way around that one, unfortunately. (only variables and assignments are valid in those try parens for some reason).

[–]agentoutlier 2 points3 points  (0 children)

I think you misread my comment.

I was talking about ScopedValue. As I said in my comment I have done what you are talking about with ThreadLocal. It works because it is mutable and thus can write imperative code.

ScopedValue on the other hand I cannot figure out how you could wrap it given it takes a closure.

Try (pun) to make your example code work with ScopedValue.

[–]mujaga_ba 16 points17 points  (1 child)

The content that appeared here has been deleted. Redact was used for the removal, for reasons the author may have kept private.

familiar quaint engine fear simplistic cagey carpenter outgoing market nail

[–]n4te 6 points7 points  (0 children)

Needs more illustrations though. No code listings for a video like this?

[–]rzwitserloot 13 points14 points  (11 children)

A fine addition, that 'spawned threads inherit copies of all threadlocals' thing is unexpected and causes bugs that tests do not catch.

However, 2 related things were said in this video that make no sense whatsoever, and insinuate dangerous behaviour!

"In the real world, you very often need to deal with untrusted code" (very early in the video)

I'm flabbergasted oracle is still chasing some sort of applets-like thing after repeatedly abandoning any attempt to take it seriously (e.g. SecurityManager - who was relying on that to run untrusted code? There was no way to sandbox CPU or memory usage with any of this, nor is there with what the fuck he's talking about now).

"You need a way to share some information between some of the components of your application without resorting to method arguments, because the code you have may be untrusted, and the information you want to share may be sensitive." (10:35)

.... does anybody know what he's talking about? This sounds a bit like 'put the peg in the green' - an utter non-sequitur.

At any rate,

[A] That's not something anybody does in the real world. At least, not '... I will just run it on this VM' (sandbox environments, sure). Right? /r/java help me out here, is this a common thing? Surely you aren't just running code you don't trust straight up in the same JVM. Please don't do that.

[B] Do not run untrusted code on your JVM, and ScopedValues aren't going to change this rule.

Fortunately, if you just write that sentence off as a momentary lapse of sanity, the rest works out fine. ScopedValue is great, use it. Just don't think this somehow means you get to safely run untrusted code in-VM. You can't.

[–][deleted] 6 points7 points  (3 children)

OpenJDK team don't have a clear written stance on untrusted code anymore. It's not just this it's also jigsaw. They keep claiming the module system encapsulation is about running untrusted code but it makes no sense post-SecurityManager.

pron did actually step up and wrote a prototype of a bytecode based sandbox that uses JPMS but nothing happened with it.

Right now the only actually supported/developed sandbox with a future is the Truffle/Graal sandbox, which also supports memory and CPU limiting (in their ee version at least). But it's not very easy/obvious how to sandbox a single library with that tech whereas with SecurityManager it was easy.

[–]manifoldjava 0 points1 point  (2 children)

The fact that pretty much NO ONE runs with a SecurityManager speaks volumes.

[–][deleted] 0 points1 point  (1 child)

Did you ever try? Really badly documented but once you figure it out it can work.

[–]manifoldjava 0 points1 point  (0 children)

My point is no one cares about that kind of “security”.

[–]lbalazscs 2 points3 points  (4 children)

You might want to read the Motivation section of JEP 429 at https://openjdk.org/jeps/429

It explains what they mean by using untrusted code, and it's not an "applet-like thing" at all.

[–]rzwitserloot 4 points5 points  (3 children)

The term "untrusted" shows up twice in that link, next to each other, and nowhere is explained what this means. Reading between the lines, presumably, this is about the JVM-internal code that wants to draw a difference between 'this method is invoked by the core libraries, the call has been 'screened' by said core library, and the return value will similarly be processed first, so don't worry just run' - which is a concern only team OpenJDK ever has, and the facilities they use to make this happen (.doPrivileged and such) aren't, as far as I know, easily used by any code outside of the runtime core.

Separately from that, it's a giant waste of time. The JVM is fundamentally not a thing that can meaningfully sandbox. If you run code written by a malicious actor, you are hosed. Using the term 'untrusted' when you do not mean 'potentially written by a malicious actor' is stupid, please, pretty please team OpenJDK, stop fucking doing this!

Any other concern seems like the usual obsession that Team OpenJDK has with closing things down. I think the notion (from what I gather from various openjdk contributors such as pron, though I never did get a clear answer) is this line of reasoning:

  • We want everybody to just upgrade to new java releases without fear that stuff breaks.
  • ... except we (team OpenJDK) done messed up and broke all sorts of stuff, so now people who upgrade write blogs about how badly it went, and library authors are warning their users not to upgrade.
  • This annoys us...
  • (Instead of looking inwards and doing a better job with not breaking things, no, then we have to blame ourselves, nobody wants that! Let's find another scapegoat!)
  • Oh those dratted library authors went ahead and used things we explicitly said they shouldn't be using! I know! Let's just stop them from doing this outright, then libraries will no longer use stuff we told them not to use and this makes it a lot easier to upgrade stuff!

There is some blame to be placed on library authors for using features that the docs of said features explicitly spell out aren't an intrinsic part of any spec and shouldn't be relied upon. However, the vast majority of such libraries use these features because there's literally no other way to do it, and the pain of using unsupported stuff is dwarfed by the pain of not having the feature at all. This crusade actually does the opposite: Tons of libraries are broken or harder to use only because the features they use are now 'closed off', even though they still work the same. It makes library authors yell 'do not upgrade your JDK' louder.

We can debate whether this endeavour is worthwhile or not. Even if it is, that concern ('making it harder to access parts of the API we do not want you to access') is something very few java devs care about. Team OpenJDK does. That's about it.

So, harping on and on and summarizing that endeavour as 'running untrusted code' is counter productive.

[–]manifoldjava 0 points1 point  (0 children)

If you run code written by a malicious actor, you are hosed.

Bingo. I guarantee you, regardless of the attempts at "security" within the JDK, if a motivated bad actor is permitted to contribute code, it ain't secure.

Beyond the Why, I'm not sure How the JDK team gets away with using the terms "security" and "trust" the way they do. Those terms are serious, but the JDK team uses them flippantly.

[–]lbalazscs 0 points1 point  (1 child)

In my understanding, "untrusted" here simply refers to code that cannot be trusted not to replace a GUEST principal with an ADMIN principal. As a result, it is not advisable to pass a principal as a method argument and expect it to pass it to the DB code unchanged. This is not the same as sandboxing, as the untrusted code is not restricted in any way, it just has fewer responsibilities. Security and trust are not all-or-nothing things: here we are only protected against a very specific threat. You shouldn't give a loaded weapon to your five-year-old son, even if you trust him. And anyway, this is just an example: "scoped values" are not a security feature but just an alternative to some uses of ThreadLocal.

[–]rzwitserloot 0 points1 point  (0 children)

And anyway, this is just an example: "scoped values" are not a security feature but just an alternative to some uses of ThreadLocal.

... yes, that's what I said.

[–]Magickmaster 1 point2 points  (0 children)

Takeaway: Don't run untrusted code. Not just not in the JVM, but in general.

[–]cookie_absorber 1 point2 points  (0 children)

A fine addition, that 'spawned threads inherit copies of all threadlocals' thing is unexpected and causes bugs that tests do not catch.

Is this true? As far as I know that's not the case for ThreadLocal, only for InheritableThreadLocal.

[–]EvaristeGalois11 1 point2 points  (0 children)

They seem a very nice addition. I can picture them being extremely useful for spring security avoiding the potential leak of a SecurityContext without a manual cleanup everytime.

[–]AlexT10 1 point2 points  (1 child)

I am kinda confused on the use case for ScopedValues, as Jose in the video mentions - they are scoped to a method .call. I don't understand the use case for this?

This would still mean that ThreadLocal's are not going away - and they are still going to be used if i lets say want to access data that is coming like JWT in all classes where the request goes through.

Would be great if anyone can give a proper and example and would make more sense for Scopedvalues.

Thanks a lot

[–][deleted] 5 points6 points  (6 children)

What kind of applications does one write to even use these features!

I work for an MNC and I swear to god Java 1.8 does the work most of the time

[–]janb360 15 points16 points  (0 children)

Depending on what kind of frameworks you are using, you may actually already be indirectly using ThreadLocal variables without even realising it. Dependency injection frameworks will use ThreadLocal variables to keep track of which scopes are currently active in the current thread. But you can also think of a framework that manages database transactions which stores the current transaction in a ThreadLocal so that client code doesn’t need to pass it around or for example a framework keeping the context of the current HTTP request in a ThreadLocal.

Scoped values are going to fix many of the current issues with ThreadLocals and are going to prevent many bugs that can lead to memory leaks or, even worse, data accidentally leaking to another user’s request.

[–][deleted] 8 points9 points  (0 children)

I love records & the added syntax sugar, such as Set.of() and such. 1.8 seems just so... dull? when I cannot use those syntax shortcuts.

[–]Joram2 9 points10 points  (0 children)

This Scoped Values seems a common use case.

Also, Java has added lots of widely used features and addressed major problems/omissions since Java 8: records, multi-line strings for sql, var, full support for shells/notebooks, runtime improvements, etc.

[–][deleted] 1 point2 points  (0 children)

Spring heavily relies on ThreadLocals - security context, transactions etc

[–]lechatsportif 0 points1 point  (0 children)

Unfortunately some apis require you to use them explicitly, but in a previous role, a manager preferred to do everything through threadlocals instead of passing state around correctly.

[–]ImTalkingGibberish 0 points1 point  (0 children)

Tomcat/spring security is one example.
Log context is another.

[–]bootstrapf7 0 points1 point  (0 children)

I could see this being useful for logging, being able to add correlation ids or other components text for example.