diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
index 7272de05d1..ec7e0bae12 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClass.java
@@ -86,6 +86,15 @@ public final class AnnotatedClass
*/
protected final boolean _collectAnnotations;
+ /**
+ * Flag that indicates whether member (Field, Method, Constructor}
+ * detection should occur: starting with 2.19 is disabled for core JDK
+ * types {@link ClassUtil#isJDKCoreClass(Class)}).
+ *
+ * @since 2.20
+ */
+ protected final boolean _collectMembers;
+
/*
/**********************************************************
/* Gathered information
@@ -152,6 +161,19 @@ public final class AnnotatedClass
_mixInResolver = mir;
_typeFactory = tf;
_collectAnnotations = collectAnnotations;
+ // But need to collect for some JDK types:
+ //
+ // - Throwables
+ _collectMembers = (type != null)
+ && (!ClassUtil.isJDKCoreClass(rawType)
+ || type.hasRawClass(Optional.class)
+ || type.hasRawClass(StackTraceElement.class)
+ || Throwable.class.isAssignableFrom(rawType)
+ || type.hasRawClass(Thread.class)
+ || type.hasRawClass(ThreadGroup.class)
+ );
+
+System.out.println(" AnnotatedClass("+_type+"), coll anno? "+collectAnnotations+" coll mem? "+_collectMembers);
}
/**
@@ -171,6 +193,7 @@ public final class AnnotatedClass
_mixInResolver = null;
_typeFactory = null;
_collectAnnotations = false;
+ _collectMembers = false;
}
/**
@@ -327,9 +350,12 @@ private final List _fields() {
List f = _fields;
if (f == null) {
// 09-Jun-2017, tatu: _type only null for primordial, placeholder array types.
- if (_type == null) {
+ // 26-Apr-2025, tatu: [databind#4907] Less introspection, skip for core JDK types
+ if (_type == null || !_collectMembers) {
+System.out.println("SKIP Collecting _fields() for "+_type);
f = Collections.emptyList();
} else {
+System.out.println("Collecting _fields() for "+_type);
f = AnnotatedFieldCollector.collectFields(_annotationIntrospector,
this, _mixInResolver, _typeFactory, _type, _collectAnnotations);
}
@@ -343,9 +369,11 @@ private final AnnotatedMethodMap _methods() {
if (m == null) {
// 09-Jun-2017, tatu: _type only null for primordial, placeholder array types.
// NOTE: would be great to have light-weight shareable maps; no such impl exists for now
- if (_type == null) {
+ if (_type == null) { // || !_collectMembers) {
+System.out.println("SKIP Collecting _methods() for: "+_type);
m = new AnnotatedMethodMap();
} else {
+System.out.println("Collecting _methods() for "+_type);
m = AnnotatedMethodCollector.collectMethods(_annotationIntrospector,
this,
_mixInResolver, _typeFactory,
@@ -359,9 +387,12 @@ private final AnnotatedMethodMap _methods() {
private final Creators _creators() {
Creators c = _creators;
if (c == null) {
- if (_type == null) {
+ // 26-Apr-2025, tatu: [databind#4907] Less introspection, skip for core JDK types
+ if (_type == null || !_collectMembers) {
+System.out.println("SKIP Collecting _creators() for: "+_type);
c = NO_CREATORS;
} else {
+System.out.println("Collecting _creators() for "+_type);
c = AnnotatedCreatorCollector.collectCreators(_annotationIntrospector,
_typeFactory,
this, _type, _primaryMixIn, _collectAnnotations);
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClassResolver.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClassResolver.java
index 55acc9f209..8ee68f7a50 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClassResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedClassResolver.java
@@ -132,6 +132,8 @@ static AnnotatedClass createArrayType(MapperConfig> config, Class> raw) {
}
AnnotatedClass resolveFully() {
+System.out.println(" AnnotatedClassResolver.resolveFully() for "+_type);
+
List superTypes = new ArrayList<>(8);
if (!_type.hasRawClass(Object.class)) {
if (_type.isInterface()) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
index 7927c39909..450dc54529 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
@@ -83,6 +83,7 @@ public BasicBeanDescription forSerialization(SerializationConfig config,
// structured types as well
desc = _findStdJdkCollectionDesc(config, type);
if (desc == null) {
+System.out.println("BasicBeanDescription.forSerialization() for "+type);
desc = BasicBeanDescription.forSerialization(collectProperties(config,
type, r, true));
}
@@ -101,6 +102,7 @@ public BasicBeanDescription forDeserialization(DeserializationConfig config,
// structured types as well
desc = _findStdJdkCollectionDesc(config, type);
if (desc == null) {
+System.out.println("BasicBeanDescription.forDeserialization() for "+type);
desc = BasicBeanDescription.forDeserialization(collectProperties(config,
type, r, false));
}
@@ -127,6 +129,7 @@ public BasicBeanDescription forCreation(DeserializationConfig config,
// structured types as well
desc = _findStdJdkCollectionDesc(config, type);
if (desc == null) {
+System.out.println("BasicBeanDescription.forCreation() for "+type);
desc = BasicBeanDescription.forDeserialization(
collectProperties(config, type, r, false));
}
@@ -170,6 +173,7 @@ public BasicBeanDescription forDirectClassAnnotations(MapperConfig> config,
protected POJOPropertiesCollector collectProperties(MapperConfig> config,
JavaType type, MixInResolver r, boolean forSerialization)
{
+System.out.println(" collectProperties() for "+type);
final AnnotatedClass classDef = _resolveAnnotatedClass(config, type, r);
final AccessorNamingStrategy accNaming = type.isRecordType()
? config.getAccessorNaming().forRecord(config, classDef)
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/Reflection4907Test.java b/src/test/java/com/fasterxml/jackson/databind/misc/Reflection4907Test.java
new file mode 100644
index 0000000000..fd690b5884
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/Reflection4907Test.java
@@ -0,0 +1,58 @@
+package com.fasterxml.jackson.databind.misc;
+
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.DatabindTestUtil;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class Reflection4907Test extends DatabindTestUtil
+{
+ static class SqlDatePojo {
+ public String name;
+ public java.sql.Date date;
+
+ public SqlDatePojo() {
+ }
+
+ public SqlDatePojo(String name, java.sql.Date date) {
+ this.name = name;
+ this.date = date;
+ }
+
+ public SqlDatePojo(java.sql.Date date) {
+ this.date = date;
+ }
+
+ public java.sql.Date getDate() {
+ return date;
+ }
+
+ public void setDate(java.sql.Date date) {
+ this.date = date;
+ }
+ }
+
+ private final ObjectMapper MAPPER = newJsonMapper();
+
+ // [databind#4907]
+ @Test
+ public void test4907Read() throws Exception {
+System.err.println("");
+ SqlDatePojo pojo = MAPPER.readValue(a2q("{'date':'2000-01-01', 'name':'foo'}"),
+ SqlDatePojo.class);
+System.err.println("");
+ assertNotNull(pojo);
+ }
+
+ // [databind#4907]
+ @Test
+ public void test4907Write() throws Exception {
+System.err.println("");
+ String json = MAPPER.writeValueAsString(new SqlDatePojo("foobar",
+ java.sql.Date.valueOf("2000-01-01")));
+ System.err.println("");
+ assertNotNull(json);
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java
index c41228d5f5..057c7621e0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java
@@ -241,8 +241,8 @@ public void testNonStandardProperties() throws Exception
public void testThreadSerialization() throws Exception
{
final Thread input = Thread.currentThread();
-// String json = MAPPER.writerWithDefaultPrettyPrinter()
-// .writeValueAsString(input);
+// System.err.println("Thread -> "+MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(input));
+
Map,?> asMap = MAPPER.convertValue(input, Map.class);
// System.err.println("PROPS -> "+asMap.keySet());