@@ -932,9 +932,14 @@ private final void _writeNonSharedString(final String text, final int len) throw
932932 @ Override
933933 public JsonGenerator writeString (char [] text , int offset , int len ) throws JacksonException
934934 {
935- // Shared strings are tricky; easiest to just construct String, call the other method
935+ // Shared strings: try char-array lookup first to avoid String allocation
936936 if (len <= MAX_SHARED_STRING_LENGTH_BYTES && _seenStringValueCount >= 0 && len > 0 ) {
937- return writeString (new String (text , offset , len ));
937+ int ix = _findSeenStringValue (text , offset , len );
938+ if (ix >= 0 ) {
939+ _verifyValueWrite ("write String value" );
940+ _writeSharedStringValueReference (ix );
941+ return this ;
942+ }
938943 }
939944 _verifyValueWrite ("write String value" );
940945 if (len == 0 ) {
@@ -984,6 +989,10 @@ public JsonGenerator writeString(char[] text, int offset, int len) throws Jackso
984989 _writeByte (BYTE_MARKER_END_OF_STRING );
985990 }
986991 }
992+ // Only allocate String here if we need to store for shared-value tracking
993+ if (len <= MAX_SHARED_STRING_LENGTH_BYTES && _seenStringValueCount >= 0 ) {
994+ _addSeenStringValue (new String (text , offset , len ));
995+ }
987996 return this ;
988997 }
989998
@@ -2590,6 +2599,40 @@ private final int _findSeenStringValue(String text)
25902599 return -1 ;
25912600 }
25922601
2602+ /**
2603+ * Lookup variant that works directly on a char array, avoiding the need
2604+ * to allocate a {@link String} just for the shared-value check.
2605+ */
2606+ private final int _findSeenStringValue (char [] text , int offset , int len )
2607+ {
2608+ // Compute hash the same way String.hashCode does
2609+ int hash = 0 ;
2610+ for (int i = offset , end = offset + len ; i < end ; ++i ) {
2611+ hash = 31 * hash + text [i ];
2612+ }
2613+ SharedStringNode head = _seenStringValues [hash & (_seenStringValues .length -1 )];
2614+ if (head != null ) {
2615+ SharedStringNode node = head ;
2616+ do {
2617+ String value = node .value ;
2618+ if (value .length () == len && value .hashCode () == hash ) {
2619+ boolean match = true ;
2620+ for (int i = 0 ; i < len ; ++i ) {
2621+ if (value .charAt (i ) != text [offset + i ]) {
2622+ match = false ;
2623+ break ;
2624+ }
2625+ }
2626+ if (match ) {
2627+ return node .index ;
2628+ }
2629+ }
2630+ node = node .next ;
2631+ } while (node != null );
2632+ }
2633+ return -1 ;
2634+ }
2635+
25932636 private final void _addSeenStringValue (String text )
25942637 {
25952638 // first: do we need to expand?
0 commit comments