aabadie: I pushed an update commit (1c7763e) that ensures the numpy array wrapper is written in a dedicated frame in the pickle byte stream. I think it's cleaner.
aabadie: @lesteve, comments addressed.
aabadie: @lesteve, I reverted to the initial solution. 
lesteve: LGTM, merging, great job!
diff --git a/joblib/numpy_pickle.py b/joblib/numpy_pickle.py
index 0cb616d..f029582 100644
--- a/joblib/numpy_pickle.py
+++ b/joblib/numpy_pickle.py
@@ -265,6 +265,14 @@ class NumpyPickler(Pickler):
             wrapper = self._create_array_wrapper(obj)
             Pickler.save(self, wrapper)
 
+            # A framer was introduced with pickle protocol 4 and we want to
+            # ensure the wrapper object is written before the numpy array
+            # buffer in the pickle file.
+            # See https://www.python.org/dev/peps/pep-3154/#framing to get
+            # more information on the framer behavior.
+            if self.proto >= 4:
+                self.framer.commit_frame(force=True)
+
             # And then array bytes are written right after the wrapper.
             wrapper.write_array(obj, self)
             return

load fails when dump use pickle.HIGHEST_PROTOCOL in Python 3
in master branch a96878e (version 0.10.0.dev0), the following code gives `KeyError`

```py
import pickle
import numpy as np
import joblib

a = np.zeros((1, 235), np.uint32)
joblib.dump(a, 'tmp.jl', protocol=pickle.HIGHEST_PROTOCOL)
joblib.load('tmp.jl')
```

That is: joblib seems do not support load data which saved with `pickle.HIGHEST_PROTOCOL`
diff --git a/joblib/test/test_numpy_pickle.py b/joblib/test/test_numpy_pickle.py
index 321a428..19a5e95 100644
--- a/joblib/test/test_numpy_pickle.py
+++ b/joblib/test/test_numpy_pickle.py
@@ -13,6 +13,7 @@ import warnings
 import nose
 import gzip
 import zlib
+import pickle
 from contextlib import closing
 
 from joblib.test.common import np, with_numpy
@@ -821,3 +822,18 @@ def test_non_contiguous_array_pickling():
         array_reloaded = numpy_pickle.load(filename)
         np.testing.assert_array_equal(array_reloaded, array)
         os.remove(filename)
+
+
+@with_numpy
+def test_pickle_highest_protocol():
+    # ensure persistence of a numpy array is valid even when using
+    # the pickle HIGHEST_PROTOCOL.
+    # see https://github.com/joblib/joblib/issues/362
+
+    filename = env['filename'] + str(random.randint(0, 1000))
+    test_array = np.zeros(10)
+
+    numpy_pickle.dump(test_array, filename, protocol=pickle.HIGHEST_PROTOCOL)
+    array_reloaded = numpy_pickle.load(filename)
+
+    np.testing.assert_array_equal(array_reloaded, test_array)

pip install -e .
parse_log_pytest
nose coverage numpy>=1.6.1 pytest
apt-get update apt-get install -y gcc
3.5
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
coverage==6.2
importlib-metadata==4.8.3
iniconfig==1.1.1
-e git+https://github.com/joblib/joblib.git@40341615cc2600675ce7457d9128fb030f6f89fa#egg=joblib
nose==1.3.7
numpy==1.19.5
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
tomli==1.2.3
typing_extensions==4.1.1
zipp==3.6.0

name: joblib
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - coverage==6.2
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - nose==1.3.7
      - numpy==1.19.5
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/joblib

joblib/test/test_numpy_pickle.py::test_pickle_highest_protocol
joblib/test/test_numpy_pickle.py::test_cache_size_warning joblib/test/test_numpy_pickle.py::test_joblib_pickle_across_python_versions
joblib/test/test_numpy_pickle.py::test_value_error joblib/test/test_numpy_pickle.py::test_compress_level_error joblib/test/test_numpy_pickle.py::test_numpy_persistence joblib/test/test_numpy_pickle.py::test_numpy_persistence_bufferred_array_compression joblib/test/test_numpy_pickle.py::test_memmap_persistence joblib/test/test_numpy_pickle.py::test_memmap_persistence_mixed_dtypes joblib/test/test_numpy_pickle.py::test_masked_array_persistence joblib/test/test_numpy_pickle.py::test_compress_mmap_mode_warning joblib/test/test_numpy_pickle.py::test_compressed_pickle_dump_and_load joblib/test/test_numpy_pickle.py::test_compress_tuple_argument joblib/test/test_numpy_pickle.py::test_joblib_compression_formats joblib/test/test_numpy_pickle.py::test_load_externally_decompressed_files joblib/test/test_numpy_pickle.py::test_compression_using_file_extension joblib/test/test_numpy_pickle.py::test_binary_zlibfile joblib/test/test_numpy_pickle.py::test_numpy_subclass joblib/test/test_numpy_pickle.py::test_pathlib joblib/test/test_numpy_pickle.py::test_non_contiguous_array_pickling
joblib/numpy_pickle.py
joblib/numpy_pickle.py