question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Stack overflow on multi maps (and other non-trivial generic classes)

See original GitHub issue

Describe the bug

Hi,

while I was testing my other work (#4354) against Keycloak operator schema, I noticed another issue. The schema generation fails with StackOverflowError.

Upon closer inspection, it looks that the problematic part is their usage of concrete multi maps like so:

private MultivaluedHashMap<String, ComponentExportRepresentation> components;
public class MultivaluedHashMap<K, V> extends HashMap<K, List<V>> { /* ...  */ }

Fabric8 Kubernetes Client version

6.0.0

Steps to reproduce

Here’s a minimal failing example:

@Group("map.fabric8.io")
@Version("v1alpha1")
public class ContainingMaps extends  CustomResource<ContainingMapsSpec, Void> {}

public class ContainingMapsSpec {
  private MyMultiMap<String, String> test3;
}

public class MyMultiMap<K, V> extends HashMap<K, List<V>> {}

Unfortunately, this cannot be avoided by using @SchemaFrom or @SchemaSwap annotations, because the Stack Overflow happens an a code path that does not process these annotations, namely in AnnotatedPropertyPathDetector

And it is not even necessary to run the full schema generation.

All that is needed to trigger the Stack Overflow (i.e. from a unit test) is:

Types.typeDefFrom(MyMultiMap.class);

Expected behavior

The problem is in the unschallow logic, implemented in Types class.

For generic types, the methods projectSuperClasses, projectDefinition, mapClassRefArguments and mapGenericProperties replace type parameters on superclasses with their concrete instantiations from usage site.

For simple types, like class IntStringMap extends HashMap<Integer,String>, this works by first creating a mapping {K -> Integer, V -> String} and thein recursively replacing all usages of K and V according to the mapping.

However, in our case, the mapping contains V -> List<V>. This gets expanded infinitely to List<List<List<...>>>, until memory is exhausted.

Obviously, expected behavior is for this to not happen, the V should only be expanded once.

Runtime

other (please specify in additional context)

Kubernetes API Server version

other (please specify in additional context)

Environment

other (please specify in additional context)

Fabric8 Kubernetes Client Logs

No response

Additional context

I think I may have a fix for the StackOverflowError, we can discuss that further, just please confirm that somebody else is not working on it already.

As a side note, even with that fixed, multimaps are still generated wrong. I may have a cure for that, too, but I’d create a separate issue.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:19 (19 by maintainers)

github_iconTop GitHub Comments

3reactions
xRodneycommented, Sep 13, 2022

Update: I have made a PR to sundrio, fixing the issue (sundrio/sundrio#340). I have also made a PR here, which however relies on the changed code, so it won’t compile for you. But locally it seems to be working.

1reaction
manusacommented, Sep 8, 2022

👍 We’ll wait for his feedback then. Tonight’s SNAPSHOT should contain the new dependency.

Read more comments on GitHub >

github_iconTop Results From Across the Web

java - Map with multiple value types with advantages of generics
I want to create a map that will provide the benefits of generics, whilst supporting multiple different types of values.
Read more >
If everyone hates it, why is OOP still so widespread?
Literally, shape-changing, this concept allows one object or method, whether it's a generic, an interface, or a regular object, to serve as the ......
Read more >
What is wrong with Java's generics? [closed]
Java's generic implementation uses type erasure. This means that your strongly typed generic collections are actually of type Object at runtime.
Read more >
Working with Indexes | Inside RavenDB
In the class constructor, we set the Map property to a Linq expression, ... The second generic parameter to Query is the index...
Read more >
LLVM Language Reference Manual
Abstract¶. This document is a reference manual for the LLVM assembly language. LLVM is a Static Single Assignment (SSA) based representation that provides ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found